diff options
Diffstat (limited to 'lib/common_test')
75 files changed, 11219 insertions, 1369 deletions
diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile index 3ea6ae65d5..d9651f13b0 100644 --- a/lib/common_test/doc/src/Makefile +++ b/lib/common_test/doc/src/Makefile @@ -61,6 +61,7 @@ XML_PART_FILES = part.xml XML_CHAPTER_FILES = \ basics_chapter.xml \ + getting_started_chapter.xml \ install_chapter.xml \ write_test_chapter.xml \ test_structure_chapter.xml \ @@ -80,7 +81,10 @@ MAKE_EDOC = make_edoc BOOK_FILES = book.xml -GIF_FILES = +GIF_FILES = \ + tc_execution.gif \ + config.gif \ + html_logs.gif INSTALL_NOTES = ../../notes.html @@ -138,12 +142,6 @@ man: $(MAN6_FILES) $(MAN3_FILES) $(MAN1_FILES) debug opt: -# -# checkout make.dep before generating new dependecies -# -#make_doc_depend: xml -# docdepend > make.dep - clean clean_docs: rm -f $(CT_XML_FILES) rm -rf $(HTMLDIR)/* @@ -176,12 +174,3 @@ release_docs_spec: docs release_spec: release_tests_spec: - -# ---------------------------------------------------- -# Include dependency -# ---------------------------------------------------- - -include make.dep -# DO NOT DELETE - - diff --git a/lib/common_test/doc/src/basics_chapter.xml b/lib/common_test/doc/src/basics_chapter.xml index c1bb365b1f..20141d2561 100644 --- a/lib/common_test/doc/src/basics_chapter.xml +++ b/lib/common_test/doc/src/basics_chapter.xml @@ -28,54 +28,65 @@ <rev></rev> <file>basics_chapter.xml</file> </header> - + <marker id="basics"></marker> <section> <title>Introduction</title> - <p> - The Common Test framework (CT) is a tool which can support - implementation and automated execution of test cases towards different - types of target systems. The framework is based on the OTP Test - Server. Test cases can be run individually or in batches. Common - Test also features a distributed testing mode with central - control and logging. This feature makes it possible to test - multiple systems independently in one common session. This - can be very useful e.g. for running automated large-scale regression - tests. + <p>The <em>Common Test</em> framework (CT) is a tool which supports + implementation and automated execution of test cases towards arbitrary + types of target systems. The CT framework is based on the OTP Test + Server and it's the main tool being used in all testing- and verification + activities that are part of Erlang/OTP system development- and maintenance. + </p> + + <p>Test cases can be executed individually or in batches. Common Test + also features a distributed testing mode with central control and logging + (a feature that makes it possible to test multiple systems independently in + one common session, useful e.g. for running automated large-scale regression + tests). </p> <p> The SUT (System Under Test) may consist of one or several target - nodes. CT contains a generic test server which together with - other test utilities is used to perform test case execution. - It is possible to start the tests from the CT GUI or from an OS- or - Erlang shell prompt. <em>Test suites</em> are files (Erlang + nodes. CT contains a generic test server which, together with + other test utilities, is used to perform test case execution. + It is possible to start the tests from a GUI or from the OS- or + Erlang shell. <em>Test suites</em> are files (Erlang modules) that contain the <em>test cases</em> (Erlang functions) to be executed. <em>Support modules</em> provide functions that the test cases utilize in order to carry out the tests. </p> - <p> - The main idea is that CT based test programs connect to - the target system(s) via standard O&M interfaces. CT - provides implementations and wrappers of some of these O&M - interfaces and will be extended with more interfaces later. - There are a number of target independent interfaces - supported in CT such as Generic Telnet, FTP etc. which can be - specialized or used directly for controlling instruments, - traffic generators etc.</p> + <p>In a black-box testing scenario, CT based test programs connect to + the target system(s) via standard O&M and CLI protocols. CT + provides implementations of, and wrapper interfaces to, some of these + protocols (most of which exist as stand-alone components and + applications in OTP). The wrappers simplify configuration and add + verbosity for logging purposes. CT will be continously extended with + useful support modules. (Note however that it's + a straightforward task to use any arbitrary Erlang/OTP component + for testing purposes with Common Test, without needing a CT wrapper + for it. It's as simple as calling Erlang functions). There + are a number of target independent interfaces supported in CT, such as + Generic Telnet, FTP, etc, which can be specialized or used + directly for controlling instruments, traffic load generators, etc. + </p> <p>Common Test is also a very useful tool for white-box testing Erlang - code since the test programs can call Erlang API functions directly. - For black-box testing Erlang software, Erlang RPC as well as - standard O&M interfaces can be used. + code (e.g. module testing), since the test programs can call exported Erlang + functions directly and there's very little overhead required for + implementing basic test suites and executing simple tests. For black-box + testing Erlang software, Erlang RPC as well as standard O&M interfaces + can for example be used. </p> <p>A test case can handle several connections towards one or several target systems, instruments and traffic generators in parallel in order to perform the necessary actions for a test. The handling of many connections in parallel is one of - the major strengths of Common Test! + the major strengths of Common Test (thanks to the efficient + support for concurrency in the Erlang runtime system - which CT users + can take great advantage of!). </p> </section> @@ -186,7 +197,7 @@ <taglist> <tag>all()</tag> - <item>Returns a list of all test cases in the suite. (Mandatory)</item> + <item>Returns a list of all test cases and groups in the suite. (Mandatory)</item> <tag>suite()</tag> <item>Info function used to return properties for the suite. (Optional)</item> <tag>groups()</tag> @@ -197,12 +208,14 @@ <tag>end_per_suite(Config)</tag> <item>Suite level configuration function, executed after the last test case. (Optional)</item> + <tag>group(GroupName)</tag> + <item>Info function used to return properties for a test case group. (Optional)</item> <tag>init_per_group(GroupName, Config)</tag> <item>Configuration function for a group, executed before the first - test case. (Mandatory if groups are defined)</item> + test case. (Optional)</item> <tag>end_per_group(GroupName, Config)</tag> <item>Configuration function for a group, executed after the last - test case. (Mandatory if groups are defined)</item> + test case. (Optional)</item> <tag>init_per_testcase(TestCase, Config)</tag> <item>Configuration function for a testcase, executed before each test case. (Optional)</item> diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml index 57b032b3fd..c7f6c7ce5c 100644 --- a/lib/common_test/doc/src/common_test_app.xml +++ b/lib/common_test/doc/src/common_test_app.xml @@ -69,12 +69,25 @@ <funcs> <func> - <name>Module:all() -> TestCases | {skip,Reason} </name> - <fsummary>Returns the list of all test cases in the module.</fsummary> + <name>Module:all() -> Tests | {skip,Reason} </name> + <fsummary>Returns the list of all test case groups and test cases + in the module.</fsummary> <type> - <v>TestCases = [atom() | {group,GroupName}]</v> - <v>Reason = term()</v> + <v>Tests = [TestCase | {group,GroupName} | + {group,GroupName,Properties} | + {group,GroupName,Properties,SubGroups}]</v> + <v>TestCase = atom()</v> <v>GroupName = atom()</v> + <v>Properties = [parallel | sequence | Shuffle | {RepeatType,N}] | + default</v> + <v>SubGroups = [{GroupName,Properties} | + {GroupName,Properties,SubGroups}]</v> + <v>Shuffle = shuffle | {shuffle,Seed}</v> + <v>Seed = {integer(),integer(),integer()}</v> + <v>RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | + repeat_until_any_ok | repeat_until_any_fail</v> + <v>N = integer() | forever</v> + <v>Reason = term()</v> </type> <desc> @@ -85,9 +98,14 @@ This list also specifies the order the cases and groups will be executed by Common Test. A test case is represented by an atom, the name of the test case function. A test case group is - represented by a <c>{group,GroupName}</c> tuple, where - <c>GroupName</c>, an atom, is the name of the group (defined - with <c>groups/0</c>).</p> + represented by a <c>group</c> tuple, where <c>GroupName</c>, + an atom, is the name of the group (defined in <c>groups/0</c>). + Execution properties for groups may also be specified, both + for a top level group and for any of its sub-groups. + Group execution properties specified here, will override + properties in the group definition (see <c>groups/0</c>). + (With value <c>default</c>, the group definition properties + will be used).</p> <p> If <c>{skip,Reason}</c> is returned, all test cases in the module will be skipped, and the <c>Reason</c> will @@ -120,22 +138,30 @@ <desc> <p> OPTIONAL </p> - <p>See <seealso marker="write_test_chapter#test_case_groups">Test case + <p>Function for defining test case groups. Please see + <seealso marker="write_test_chapter#test_case_groups">Test case groups</seealso> in the User's Guide for details.</p> </desc> </func> <func> <name>Module:suite() -> [Info] </name> - <fsummary>Test suite info function (providing default data for the suite).</fsummary> + <fsummary>Test suite info function (providing default data + for the suite).</fsummary> <type> <v> Info = {timetrap,Time} | {require,Required} | {require,Name,Required} | {userdata,UserData} | {silent_connections,Conns} | {stylesheet,CSSFile} | {ct_hooks, CTHs}</v> - <v> Time = MilliSec | {seconds,integer()} | {minutes,integer()} - | {hours,integer()}</v> + <v> Time = TimeVal | TimeFunc</v> + <v> TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} | + {hours,integer()}</v> + <v> TimeFunc = {Mod,Func,Args} | Fun</v> <v> MilliSec = integer()</v> + <v> Mod = atom()</v> + <v> Func = atom()</v> + <v> Args = list()</v> + <v> Fun = fun()</v> <v> Required = Key | {Key,SubKeys}</v> <v> Key = atom()</v> <v> SubKeys = SubKey | [SubKey]</v> @@ -154,19 +180,21 @@ <p>This is the test suite info function. It is supposed to return a list of tagged tuples that specify various properties - regarding the execution of this test suite (common for all + related to the execution of this test suite (common for all test cases in the suite).</p> <p>The <c>timetrap</c> tag sets the maximum time each - test case is allowed to take (including <c>init_per_testcase/2</c> + test case is allowed to execute (including <c>init_per_testcase/2</c> and <c>end_per_testcase/2</c>). If the timetrap time is exceeded, the test case fails with reason - <c>timetrap_timeout</c>.</p> + <c>timetrap_timeout</c>. If a <c>TimeFunc</c> function is specified, + it will be called initially and must return a value on + <c>TimeVal</c> format.</p> <p>The <c>require</c> tag specifies configuration variables - that are required by test cases in the suite. If the required - configuration variables are not found in any of the - configuration files, all test cases are skipped. For more + that are required by test cases (and/or configuration functions) + in the suite. If the required configuration variables are not found + in any of the configuration files, all test cases are skipped. For more information about the 'require' functionality, see the reference manual for the function <c>ct:require/[1,2]</c>.</p> @@ -188,8 +216,9 @@ </func> <func> - <name>Module:init_per_suite(Config) -> NewConfig | {skip,Reason} | {skip_and_save,Reason,SaveConfig}</name> - <fsummary>Test suite initialization.</fsummary> + <name>Module:init_per_suite(Config) -> NewConfig | {skip,Reason} | + {skip_and_save,Reason,SaveConfig}</name> + <fsummary>Test suite initializations.</fsummary> <type> <v> Config = NewConfig = SaveConfig = [{Key,Value}]</v> <v> Key = atom()</v> @@ -200,15 +229,15 @@ <p> OPTIONAL </p> - <p>This function is called as the first function in the - suite. It typically contains initialization which is common for + <p>This configuration function is called as the first function in the + suite. It typically contains initializations which are common for all test cases in the suite, and which shall only be done - once. The <c>Config</c> parameter is the configuration + once. The <c>Config</c> parameter is the configuration data which can be modified here. Whatever is returned from this function is given as <c>Config</c> to all configuration functions and test cases in the suite. If <c>{skip,Reason}</c> - is returned, all test cases in the suite will be skipped and <c>Reason</c> - printed in the overview log for the suite.</p> + is returned, all test cases in the suite will be skipped + and <c>Reason</c> printed in the overview log for the suite.</p> <p>For information on <c>save_config</c> and <c>skip_and_save</c>, please see <seealso marker="dependencies_chapter#save_config">Dependencies @@ -216,29 +245,106 @@ </desc> </func> - <func> - <name>Module:end_per_suite(Config) -> void() | {save_config,SaveConfig}</name> - <fsummary>Test suite finalization. </fsummary> - <type> - <v> Config = SaveConfig = [{Key,Value}]</v> - <v> Key = atom()</v> - <v> Value = term()</v> - </type> + <func> + <name>Module:end_per_suite(Config) -> void() | + {save_config,SaveConfig}</name> + <fsummary>Test suite finalization. </fsummary> + <type> + <v> Config = SaveConfig = [{Key,Value}]</v> + <v> Key = atom()</v> + <v> Value = term()</v> + </type> + + <desc> + <p> OPTIONAL </p> + <p>This function is called as the last test case in the + suite. It is meant to be used for cleaning up after + <c>init_per_suite/1</c>. + For information on <c>save_config</c>, please see + <seealso marker="dependencies_chapter#save_config">Dependencies + between Test Cases and Suites</seealso> in the User's Guide.</p> + </desc> + </func> + + <func> + <name>Module:group(GroupName) -> [Info] </name> + <fsummary>Test case group info function (providing default data + for a test case group, i.e. its test cases and sub-groups).</fsummary> + <type> + <v> Info = {timetrap,Time} | {require,Required} | + {require,Name,Required} | {userdata,UserData} | + {silent_connections,Conns} | {stylesheet,CSSFile} | + {ct_hooks, CTHs}</v> + <v> Time = TimeVal | TimeFunc</v> + <v> TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} | + {hours,integer()}</v> + <v> TimeFunc = {Mod,Func,Args} | Fun</v> + <v> MilliSec = integer()</v> + <v> Mod = atom()</v> + <v> Func = atom()</v> + <v> Args = list()</v> + <v> Fun = fun()</v> + <v> Required = Key | {Key,SubKeys}</v> + <v> Key = atom()</v> + <v> SubKeys = SubKey | [SubKey]</v> + <v> SubKey = atom()</v> + <v> Name = atom()</v> + <v> UserData = term()</v> + <v> Conns = [atom()]</v> + <v> CSSFile = string()</v> + <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs} | + {CTHModule, CTHInitArgs, CTHPriority}]</v> + <v> CTHModule = atom()</v> + <v> CTHInitArgs = term()</v> + </type> <desc> + <p> OPTIONAL </p> - <p>This function is called as the last test case in the - suite. It is meant to be used for cleaning up after <c>init_per_suite/1</c>. - For information on <c>save_config</c>, please see - <seealso marker="dependencies_chapter#save_config">Dependencies between - Test Cases and Suites</seealso> in the User's Guide.</p> - </desc> + <p>This is the test case group info function. It is supposed to + return a list of tagged tuples that specify various properties + related to the execution of a test case group (i.e. its test cases + and sub-groups). Properties set by <c>groups/1</c> override + properties with the same key that have been previously set by + <c>suite/0</c>.</p> + + <p>The <c>timetrap</c> tag sets the maximum time each + test case is allowed to execute (including <c>init_per_testcase/2</c> + and <c>end_per_testcase/2</c>). If the timetrap time is + exceeded, the test case fails with reason + <c>timetrap_timeout</c>. If a <c>TimeFunc</c> function is specified, + it will be called initially and must return a value on + <c>TimeVal</c> format.</p> + + <p>The <c>require</c> tag specifies configuration variables + that are required by test cases (and/or configuration functions) + in the suite. If the required configuration variables are not found + in any of the configuration files, all test cases in this group are skipped. + For more information about the 'require' functionality, see the + reference manual for the function + <c>ct:require/[1,2]</c>.</p> + + <p>With <c>userdata</c>, it is possible for the user to + specify arbitrary test case group related information which can be + read by calling <c>ct:userdata/2</c>.</p> + + <p>The <c>ct_hooks</c> tag specifies which + <seealso marker="ct_hooks_chapter">Common Test Hooks</seealso> + are to be run together with this suite.</p> + + <p>Other tuples than the ones defined will simply be ignored.</p> + + <p>For more information about the test case group info function, + see <seealso marker="write_test_chapter#suite">Test + case group info function</seealso> in the User's Guide.</p> + </desc> </func> <func> - <name>Module:init_per_group(GroupName, Config) -> NewConfig | {skip,Reason}</name> - <fsummary>Test case group initialization.</fsummary> + <name>Module:init_per_group(GroupName, Config) -> NewConfig | + {skip,Reason}</name> + <fsummary>Test case group initializations.</fsummary> <type> <v> GroupName = atom()</v> <v> Config = NewConfig = [{Key,Value}]</v> @@ -248,18 +354,18 @@ </type> <desc> - <p> MANDATORY (only if one or more groups are defined) </p> + <p> OPTIONAL </p> - <p>This function is called before execution of a test case group. - It typically contains initialization which is common for - all test cases in the group, and which shall only be performed - once. <c>GroupName</c> is the name of the group, as specified in - the group definition (see <c>groups/0</c>). The <c>Config</c> - parameter is the configuration which can be modified here. - Whatever is returned from this function is given as <c>Config</c> - to all test cases in the group. If <c>{skip,Reason}</c> is returned, - all test cases in the group will be skipped and <c>Reason</c> printed - in the overview log for the group.</p> + <p>This configuration function is called before execution of a + test case group. It typically contains initializations which are + common for all test cases and sub-groups in the group, and which + shall only be performed once. <c>GroupName</c> is the name of the + group, as specified in the group definition (see <c>groups/0</c>). The + <c>Config</c> parameter is the configuration data which can be modified + here. The return value of this function is given as <c>Config</c> + to all test cases and sub-groups in the group. If <c>{skip,Reason}</c> + is returned, all test cases in the group will be skipped and + <c>Reason</c> printed in the overview log for the group.</p> <p>For information about test case groups, please see <seealso marker="write_test_chapter#test_case_groups">Test case @@ -268,7 +374,8 @@ </func> <func> - <name>Module:end_per_group(GroupName, Config) -> void() | {return_group_result,Status}</name> + <name>Module:end_per_group(GroupName, Config) -> void() | + {return_group_result,Status}</name> <fsummary>Test case group finalization.</fsummary> <type> <v> GroupName = atom()</v> @@ -279,7 +386,7 @@ </type> <desc> - <p> MANDATORY (only if one or more groups are defined) </p> + <p> OPTIONAL </p> <p>This function is called after the execution of a test case group is finished. It is meant to be used for cleaning up after <c>init_per_group/2</c>. @@ -297,7 +404,7 @@ <func> <name>Module:init_per_testcase(TestCase, Config) -> NewConfig | {fail,Reason} | {skip,Reason}</name> - <fsummary>Test case initialization.</fsummary> + <fsummary>Test case initializations.</fsummary> <type> <v> TestCase = atom()</v> <v> Config = NewConfig = [{Key,Value}]</v> @@ -353,9 +460,15 @@ <v> Info = {timetrap,Time} | {require,Required} | {require,Name,Required} | {userdata,UserData} | {silent_connections,Conns}</v> - <v> Time = MilliSec | {seconds,integer()} | {minutes,integer()} - | {hours,integer()}</v> + <v> Time = TimeVal | TimeFunc</v> + <v> TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} | + {hours,integer()}</v> + <v> TimeFunc = {Mod,Func,Args} | Fun</v> <v> MilliSec = integer()</v> + <v> Mod = atom()</v> + <v> Func = atom()</v> + <v> Args = list()</v> + <v> Fun = fun()</v> <v> Required = Key | {Key,SubKeys}</v> <v> Key = atom()</v> <v> SubKeys = SubKey | [SubKey]</v> @@ -371,26 +484,31 @@ <p>This is the test case info function. It is supposed to return a list of tagged tuples that specify various properties - regarding the execution of this particular test case.</p> + related to the execution of this particular test case. + Properties set by <c>Testcase/0</c> override + properties that have been previously set for the test case + by <c>group/1</c> or <c>suite/0</c>.</p> <p>The <c>timetrap</c> tag sets the maximum time the - test case is allowed to take. If the timetrap time is + test case is allowed to execute. If the timetrap time is exceeded, the test case fails with reason <c>timetrap_timeout</c>. <c>init_per_testcase/2</c> and <c>end_per_testcase/2</c> are included in the - timetrap time.</p> + timetrap time. If a <c>TimeFunc</c> function is specified, + it will be called before the test case (or <c>init_per_testcase/2</c>) + and must return a value on <c>TimeVal</c> format.</p> <p>The <c>require</c> tag specifies configuration variables - that are required by the test case. If the required - configuration variables are not found in any of the + that are required by the test case (and/or <c>init/end_per_testcase/2</c>). + If the required configuration variables are not found in any of the configuration files, the test case is skipped. For more information about the 'require' functionality, see the reference manual for the function <c>ct:require/[1,2]</c>.</p> <p>If <c>timetrap</c> and/or <c>require</c> is not set, the - default values specified in the <c>suite/0</c> return list - will be used.</p> + default values specified by <c>suite/0</c> (or + <c>group/1</c>) will be used.</p> <p>With <c>userdata</c>, it is possible for the user to specify arbitrary test case related information which can be @@ -422,12 +540,12 @@ <p>This is the implementation of a test case. Here you must call the functions you want to test, and do whatever you need to check the result. If something fails, make sure the - function causes a runtime error, or call <c>ct:fail/[0,1]</c> - (which also causes the test case process to crash).</p> + function causes a runtime error, or call <c>ct:fail/1/2</c> + (which also causes the test case process to terminate).</p> - <p>Elements from the <c>Config</c> parameter can be read - with the <c>?config</c> macro. The <c>config</c> - macro is defined in <c>ct.hrl</c></p> + <p>Elements from the <c>Config</c> list can e.g. be read + with <c>proplists:get_value/2</c> (or the macro <c>?config</c> + defined in <c>ct.hrl</c>).</p> <p>You can return <c>{skip,Reason}</c> if you decide not to run the test case after all. <c>Reason</c> will then be diff --git a/lib/common_test/doc/src/config.gif b/lib/common_test/doc/src/config.gif Binary files differnew file mode 100644 index 0000000000..ac8006c4fb --- /dev/null +++ b/lib/common_test/doc/src/config.gif diff --git a/lib/common_test/doc/src/config_file_chapter.xml b/lib/common_test/doc/src/config_file_chapter.xml index 59151a73ec..6a860bb58b 100644 --- a/lib/common_test/doc/src/config_file_chapter.xml +++ b/lib/common_test/doc/src/config_file_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2010</year> + <year>2004</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -285,7 +285,7 @@ <c>{ok, Config}</c> - if the configuration variables are read successfully, </item> <item> - <c>{error, Error, ErrorDetails}</c> - if the callback module fails to + <c>{error, {Error, ErrorDetails}}</c> - if the callback module fails to proceed with the given configuration parameters. </item> </list> @@ -422,14 +422,14 @@ stop()-> call(Client, Request)-> case whereis(?REGISTERED_NAME) of undefined-> - {error, not_started, Request}; + {error, {not_started, Request}}; Pid-> Pid ! {Client, Request}, receive Reply-> {ok, Reply} after 4000-> - {error, timeout, Request} + {error, {timeout, Request}} end end. diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml index 0ece3199bb..b98c04a850 100644 --- a/lib/common_test/doc/src/ct_hooks.xml +++ b/lib/common_test/doc/src/ct_hooks.xml @@ -37,12 +37,6 @@ <description> - <warning><p>This feature is in alpha release right now. This means that the - interface may change in the future and that there may be bugs. We - encourage you to use this feature, but be prepared - that there might be bugs and that the interface might change - inbetween releases.</p></warning> - <p>The <em>Common Test Hook</em> (henceforth called CTH) framework allows extensions of the default behaviour of Common Test by means of callbacks before and after all test suite calls. It is meant for advanced users of @@ -302,7 +296,7 @@ <p>Note that it is not possible to add CTH's here right now, that feature might be added later, - but it would right now break backwards compatability.</p> + but it would right now break backwards compatibility.</p> </desc> </func> diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml index dbb4310040..8505ee8469 100644 --- a/lib/common_test/doc/src/ct_hooks_chapter.xml +++ b/lib/common_test/doc/src/ct_hooks_chapter.xml @@ -32,11 +32,6 @@ <marker id="general"></marker> <section> <title>General</title> - <warning><p>This feature is in alpha release right now. This means that the - interface may change in the future and that there may be bugs. We - encourage you to use this feature, but be prepared - that there might be bugs and that the interface might change - inbetween releases.</p></warning> <p> The <em>Common Test Hook</em> (henceforth called CTH) framework allows extensions of the default behaviour of Common Test by means of hooks @@ -113,9 +108,10 @@ </section> <section> - <title>CTH Priority</title> + <title>CTH Execution order</title> <p>By default each CTH installed will be executed in the order which - they are installed. This is not always wanted so common_test allows + they are installed for init calls, and then reversed for end calls. + This is not always wanted so common_test allows the user to specify a priority for each hook. The priority can either be specified in the CTH <seealso marker="ct_hooks#Module:init-2">init/2 </seealso> function or when installing the hook. The priority given at @@ -405,6 +401,38 @@ terminate(State) -> ok.</code> </section> + <marker id="builtin_cths"/> + <section> + <title>Built-in CTHs</title> + <p>Common Test is delivered with a couple of general purpose CTHs that + can be enabled by the user to provide some generic testing functionality. + Some of these are enabled by default when starting running common_test, + they can be disabled by setting <c>enable_builtin_hooks</c> to + <c>false</c> on the command line or in the test specification. In the + table below there is a list of all current CTHs which are delivered with + Common Test.</p> + + <table> + <row> + <cell><em>CTH Name</em></cell> + <cell><em>Is Built-in</em></cell> + <cell><em>Description</em></cell> + </row> + <row> + <cell>cth_log_redirect</cell> + <cell>yes</cell> + <cell>Captures all error_logger and SASL logging events and prints them + to the current test case log. If an event can not be associated with a + testcase it will be printed in the common test framework log. This will + happen for testcases which are run in parallel and events which occur + inbetween testcases. You can configure the level of + <seealso marker="sasl:sasl_app">SASL</seealso> events report + using the normal SASL mechanisms. </cell> + </row> + </table> + + </section> + </chapter> diff --git a/lib/common_test/doc/src/ct_run.xml b/lib/common_test/doc/src/ct_run.xml index 1ab563d74f..b01ab3667d 100644 --- a/lib/common_test/doc/src/ct_run.xml +++ b/lib/common_test/doc/src/ct_run.xml @@ -4,7 +4,7 @@ <comref> <header> <copyright> - <year>2007</year><year>2010</year> + <year>2007</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -83,7 +83,7 @@ <title>Run tests from command line</title> <pre> ct_run [-dir TestDir1 TestDir2 .. TestDirN] | - [-suite Suite1 Suite2 .. SuiteN + [[-dir TestDir] -suite Suite1 Suite2 .. SuiteN [[-group Group1 Group2 .. GroupN] [-case Case1 Case2 .. CaseN]]] [-step [config | keep_inactive]] [-config ConfigFile1 ConfigFile2 .. ConfigFileN] @@ -92,6 +92,7 @@ [-decrypt_key Key] | [-decrypt_file KeyFile] [-label Label] [-logdir LogDir] + [-logopts LogOpts] [-silent_connections [ConnType1 ConnType2 .. ConnTypeN]] [-stylesheet CSSFile] [-cover CoverCfgFile] @@ -117,6 +118,7 @@ [-decrypt_key Key] | [-decrypt_file KeyFile] [-label Label] [-logdir LogDir] + [-logopts LogOpts] [-allow_user_terms] [-silent_connections [ConnType1 ConnType2 .. ConnTypeN]] [-stylesheet CSSFile] @@ -138,10 +140,11 @@ <pre> ct_run -vts [-browser Browser] [-dir TestDir1 TestDir2 .. TestDirN] | - [-suite Suite [[-group Group] [-case Case]]] + [[dir TestDir] -suite Suite [[-group Group] [-case Case]]] [-config ConfigFile1 ConfigFile2 .. ConfigFileN] [-userconfig CallbackModule1 ConfigString1 and CallbackModule2 ConfigString2 and .. and CallbackModuleN ConfigStringN] + [-logopts LogOpts] [-decrypt_key Key] | [-decrypt_file KeyFile] [-include InclDir1 InclDir2 .. InclDirN] [-no_auto_compile] diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml index b41b233ce6..a5886b9687 100644 --- a/lib/common_test/doc/src/event_handler_chapter.xml +++ b/lib/common_test/doc/src/event_handler_chapter.xml @@ -174,6 +174,16 @@ are also given. </p></item> + <item><c>#event{name = tc_logfile, data = {{Suite,Func},LogFileName}}</c> + <p><c>Suite = atom()</c>, name of the test suite.</p> + <p><c>Func = atom()</c>, name of test case or configuration function.</p> + <p><c>LogFileName = string()</c>, full name of test case log file.</p> + <p>This event is sent at the start of each test case (and configuration function + except <c>init/end_per_testcase</c>) and carries information about the + full name (i.e. the file name including the absolute directory path) of + the current test case log file. + </p></item> + <marker id="tc_done"/> <item><c>#event{name = tc_done, data = {Suite,FuncOrGroup,Result}}</c> <p><c>Suite = atom()</c>, name of the suite.</p> diff --git a/lib/common_test/doc/src/filestruct.gif b/lib/common_test/doc/src/filestruct.gif Binary files differindex 2b06833d0b..2b06833d0b 100755..100644 --- a/lib/common_test/doc/src/filestruct.gif +++ b/lib/common_test/doc/src/filestruct.gif diff --git a/lib/common_test/doc/src/getting_started_chapter.xml b/lib/common_test/doc/src/getting_started_chapter.xml new file mode 100644 index 0000000000..7de0912036 --- /dev/null +++ b/lib/common_test/doc/src/getting_started_chapter.xml @@ -0,0 +1,230 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2007</year><year>2010</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + 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. + + </legalnotice> + + <title>Getting Started</title> + <prepared>Peter Andersson</prepared> + <docno></docno> + <date>2011-12-12</date> + <rev></rev> + <file>getting_started_chapter.xml</file> + </header> + + <section> + <title>Are you new around here?</title> + <p> + The purpose of this short chapter is to, with a "learning by example" + approach, give the newcomer a chance to get started quickly writing and + executing some first simple tests. The chapter will introduce some of the + basics, but leave most explanations and details for the later + chapters in this User's Guide. Hopefully though, after this chapter, you + will be inspired and unintimidated enough to go on and get into the + nitty-gritty that follows in this rather heavy User's Guide! If you're + not much into "learning by example" and prefer to get into more technical + detail right away, go ahead and skip to the next chapter. Again, the basics + presented here will be covered in detail in later chapters. + </p> + <p> + This chapter also tries to demonstrate how dead simple it actually is + to write a very basic (yet for many module testing purposes, often sufficiently + complex) test suite, and execute its test cases. This is not necessarily + obvious when you read the rest of the chapters in the User's Guide. + </p> + <p> + A quick note before we start: In order to understand what's discussed and + examplified here, it is recommended that you first read through the + opening <seealso marker="basics_chapter#basics">Common Test Basics</seealso> + chapter. + </p> + </section> + + <section> + <title>Test case execution</title> + <p>Execution of test cases is handled this way:</p> + + <p> + <image file="tc_execution.gif"> + <icaption> + Successful vs unsuccessful test case execution. + </icaption> + </image> + </p> + + <p>For each test case that Common Test is told to execute, it spawns a + dedicated process on which the test case function in question starts + running. (In parallel to the test case process, an idle waiting timer + process is started which is linked to the test case process. If the timer + process runs out of waiting time, it sends an exit signal to terminate + the test case process and this is what's called a <em>timetrap</em>). + </p> + <p>In scenario 1, the test case process terminates normally after case A has + finished executing its test code without detecting any errors. The test + case function simply returns a value and Common Test logs the test case as + successful. + </p> + <p>In scenario 2, an error is detected during test case execution + which causes the test case B function to generate an exception. + This causes the test case process to exit with reason + other than normal, and as a result, Common Test will log this as an + unsuccessful test case. + </p> + <p>As you can understand from the illustration above, Common Test requires + that a test case generates a runtime error to indicate failure (e.g. + by causing a bad match error or by calling <c>exit/1</c>, preferrably + through the <c>ct:fail/1/2</c> help function). A succesful execution is + indicated by means of a normal return from the test case function. + </p> + </section> + + <section> + <title>A simple test suite</title> + <p>As you've seen in the basics chapter, the test suite module implements + callback functions (mandatory or optional) for various purposes, e.g: + <list> + <item>Init/end configuration function for the test suite</item> + <item>Init/end configuration function for a test case</item> + <item>Init/end configuration function for a test case group</item> + <item>Test cases</item> + </list> + The configuration functions are optional and if you don't need them for + your test, a test suite with one simple test case could look like this: + </p> + <pre> + -module(my1st_SUITE). + -compile(export_all). + + all() -> + [mod_exists]. + + mod_exists(_) -> + {module,mymod} = code:load_file(mymod).</pre> + <p> + In this example we check that the <c>mymod</c> module exists (i.e. can be + successfully loaded by the code server). If the operation fails, we will + get a bad match error which terminates the test case. + </p> + </section> + + <section> + <title>A test suite with configuration functions</title> + <p> + If we need to perform configuration operations in order to run our test, we + implement configuration functions in our suite. The result from a + configuration function is configuration data, or simply <em><c>Config</c></em>. + This is a list of key-value tuples which get passed from the configuration + function to the test cases (possibly through configuration functions on + "lower level"). The data flow looks like this: + </p> + + <p> + <image file="config.gif"> + <icaption> + Config data flow in the suite. + </icaption> + </image> + </p> + + <p> + Here's an example of a test suite which uses configuration functions + to open and close a log file for the test cases (an operation that would + be unnecessary and irrelevant to perform by each test case): + </p> + <pre> + -module(check_log_SUITE). + -export([all/0, init_per_suite/1, end_per_suite/1]). + -export([check_restart_result/1, check_no_errors/1]). + + -define(value(Key,Config), proplists:get_value(Key,Config)). + + all() -> [check_restart_result, check_no_errors]. + + init_per_suite(InitConfigData) -> + [{logref,open_log()} | InitConfigData]. + + end_per_suite(ConfigData) -> + close_log(?value(logref, ConfigData)). + + check_restart_result(ConfigData) -> + TestData = read_log(restart, ?value(logref, ConfigData)), + {match,_Line} = search_for("restart successful", TestData). + + check_no_errors(ConfigData) -> + TestData = read_log(all, ?value(logref, ConfigData)), + case search_for("error", TestData) of + {match,Line} -> ct:fail({error_found_in_log,Line}); + nomatch -> ok + end.</pre> + <p> + In this example we have test cases that verify, by parsing a + log file, that our SUT has performed a successful restart and + that no unexpected errors have been printed. + </p> + + <p>To execute the test cases in the test suite above, we could type this on + the Unix/Linux command line (assuming for this example that the suite module + is in the current working directory): + </p> + <pre> + $ ct_run -dir .</pre> + <p>or</p> + <pre> + $ ct_run -suite check_log_SUITE</pre> + + <p>If we want to use the Erlang shell to run our test, we could evaluate this call: + </p> + <pre> + 1> ct:run_test([{dir, "."}]).</pre> + <p>or</p> + <pre> + 1> ct:run_test([{suite, "check_log_SUITE"}]).</pre> + <p> + The result from running our test is printed in log files on HTML format + (stored in unique log directories on different level). This illustration + shows the log file structure: + </p> + + <p> + <image file="html_logs.gif"> + <icaption> + HTML log file structure. + </icaption> + </image> + </p> + </section> + + <section> + <title>What happens next?</title> + <p> + You will find detailed information about the basics introduced here in this + chapter in the following chapters in the User's Guide, as well as + presentations of many more useful features. Have fun! + </p> + </section> +</chapter> + + + + + + + + diff --git a/lib/common_test/doc/src/html_logs.gif b/lib/common_test/doc/src/html_logs.gif Binary files differnew file mode 100644 index 0000000000..3a3fd86bde --- /dev/null +++ b/lib/common_test/doc/src/html_logs.gif diff --git a/lib/common_test/doc/src/make.dep b/lib/common_test/doc/src/make.dep deleted file mode 100644 index e34075888d..0000000000 --- a/lib/common_test/doc/src/make.dep +++ /dev/null @@ -1,27 +0,0 @@ -# ---------------------------------------------------- -# >>>> Do not edit this file <<<< -# This file was automaticly generated by -# /home/otp/bin/docdepend -# ---------------------------------------------------- - - -# ---------------------------------------------------- -# TeX files that the DVI file depend on -# ---------------------------------------------------- - -book.dvi: basics_chapter.tex book.tex common_test_app.tex \ - config_file_chapter.tex cover_chapter.tex \ - ct.tex ct_cover.tex ct_ftp.tex ct_master.tex \ - ct_master_chapter.tex ct_rpc.tex ct_snmp.tex \ - ct_ssh.tex ct_telnet.tex dependencies_chapter.tex \ - event_handler_chapter.tex example_chapter.tex \ - install_chapter.tex part.tex ref_man.tex run_test.tex \ - run_test_chapter.tex test_structure_chapter.tex \ - unix_telnet.tex why_test_chapter.tex write_test_chapter.tex - -# ---------------------------------------------------- -# Source inlined when transforming from source to LaTeX -# ---------------------------------------------------- - -book.tex: ref_man.xml - diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index 826b3c598d..da0b6b2d65 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -32,6 +32,386 @@ <file>notes.xml</file> </header> +<section><title>Common_Test 1.6</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A Getting Started chapter has been added to the Common + Test User's Guide.</p> + <p> + Own Id: OTP-9156</p> + </item> + <item> + <p> + The test case group info function has been implemented in + Common Test. Before execution of a test case group, a + call is now made to <c>TestSuite:group(GroupName)</c>. + The function returns a list of test properties, e.g. to + specify timetrap values, require configuration data, etc + (analogue to the test suite- and test case info + function). The scope of the properties set by + <c>group(GroupName)</c> is all test cases and sub-groups + of group <c>GroupName</c>.</p> + <p> + Own Id: OTP-9235</p> + </item> + <item> + <p> + Common Test hooks are now in a final supported version. + The Common Test hooks allow you to abstract out + initialization behaviour that is common to multiple test + suites into one place and also extend the behaviour of a + suite without changing the suite itself. For more + information see the Common Test user's guide.</p> + <p> + Own Id: OTP-9449</p> + </item> + <item> + <p> + A new built-in common test hook has been added which + captures error_logger and SASL event and prints them in + the testcase log. To disable this (and any other built-in + hooks) pass 'enable_builtin_hooks false' to common test.</p> + <p> + Own Id: OTP-9543</p> + </item> + <item> + <p> + Common Test now calls info functions also for the + <c>init/end_per_suite/1</c> and + <c>init/end_per_group/2</c> configuration functions. + These can be used e.g. to set timetraps and require + external configuration data relevant only for the + configuration functions in question (without affecting + properties set for groups and test cases in the suite). + The info function for <c>init/end_per_suite(Config)</c> + is <c>init/end_per_suite()</c>, and for + <c>init/end_per_group(GroupName,Config)</c> it's + <c>init/end_per_group(GroupName)</c>. Info functions can + not be used with <c>init/end_per_testcase(TestCase, + Config)</c>, since these configuration functions execute + on the test case process and will use the same properties + as the test case (i.e. properties set by the test case + info function, <c>TestCase()</c>).</p> + <p> + Own Id: OTP-9569</p> + </item> + <item> + <p> + It's now possible to read the full name of the test case + log file during execution. One way to do this is to + lookup it up as value of the key <c>tc_logfile</c> in the + test case <c>Config</c> list (which means it can also be + read by a pre- or post Common Test hook function). The + data is also sent with the event + <c>#event{name=tc_logfile,data={{Suite,Func},LogFileName}}</c>, + and can be read by any installed event handler.</p> + <p> + Own Id: OTP-9676 Aux Id: seq11941 </p> + </item> + <item> + <p> + The look of the HTML log files generated by Common Test + and Test Server has been improved (and made easier to + customize) by means of a CSS file.</p> + <p> + Own Id: OTP-9706</p> + </item> + <item> + <p> + Functions ct:fail(Format, Args) and ct:comment(Format, + Args) have been added in order to make printouts of + formatted error and comment strings easier (no need for + the user to call io_lib:format/2 explicitly).</p> + <p> + Own Id: OTP-9709 Aux Id: seq11951 </p> + </item> + <item> + <p> + The order in which ct hooks are executed for cleanup + hooks (i.e. *_end_per_* hooks) has been reversed.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-9774 Aux Id: seq11913 </p> + </item> + <item> + <p> + Printouts to stdout may be captured during test case + execution. This is useful in order to e.g. read and parse + tty printouts from the SUT during test case execution (if + necessary, say, to determine the outcome of the test). + The capturing session is started with + <c>ct:capture_start/0</c>, and stopped with + <c>ct:capture_stop/0</c>. The list of buffered strings is + read and purged with <c>ct:capture_get/0/1</c>. It's + possible to filter out printouts made with + <c>ct:log/2/3</c> and <c>ct:pal/2/3</c> from the captured + list of strings. This is done by calling + <c>capture_get/1</c> with a list of log categories to + exclude.</p> + <p> + Own Id: OTP-9775</p> + </item> + <item> + <p> + The syntax for specifying test case groups in the all/0 + list has been extended to include execution properties + for both groups and sub-groups. The properties specified + in all/0 for a group overrides the properties specified + in the group declaration (in groups/0). The main purpose + of this extension is to make it possible to run the same + set of tests, but with different properties, without + having to declare copies of the group in question. Also, + the same syntax may be used in test specifications in + order to change properties of groups at the time of + execution, without having to edit the test suite. Please + see the User's Guide for details and examples.</p> + <p> + Own Id: OTP-9809 Aux Id: OTP-9235 </p> + </item> + </list> + </section> + + + <section><title>Known Bugs and Problems</title> + <list> + <item> + <p> + Fix problems in CT/TS due to line numbers in exceptions.</p> + <p> + Own Id: OTP-9203</p> + </item> + </list> + </section> + +</section> + +<section><title>Common_Test 1.5.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + An error in how comments are colored in the test suite + overview html log file has been corrected. As result, a + new framework callback function, format_comment/1, has + been introduced.</p> + <p> + Own Id: OTP-9237</p> + </item> + <item> + <p> + Automatically generated init- and end-configuration + functions for test case groups caused incorrect execution + order of test cases. This has been corrected.</p> + <p> + Own Id: OTP-9369</p> + </item> + <item> + <p> + If multiple directories were specified with the 'logdir' + flag/option, Common Test would crash. This has been fixed + so that an error is properly reported instead.</p> + <p> + Own Id: OTP-9370</p> + </item> + <item> + <p> + If ct:log/2 was called with bad arguments, this could + cause the Common Test IO handling process to crash. This + fault has been corrected.</p> + <p> + Own Id: OTP-9371 Aux Id: OTP-8933 </p> + </item> + <item> + <p> + A bug has been fixed that made Test Server call the + end_tc/3 framework function with an incorrect module name + as first argument.</p> + <p> + Own Id: OTP-9379 Aux Id: seq11863 </p> + </item> + <item> + <p> + If a timetrap timeout occured during execution of of a + function in a lib module (i.e. a function called directly + or indirectly from a test case), the Suite argument in + the end_tc/3 framework callback function would not + correctly contain the name of the test suite, but the lib + module. (This would only happen if the lib module was + compiled with ct.hrl included). This error has been + solved.</p> + <p> + Own Id: OTP-9398</p> + </item> + <item> + <p> + Corrections of the vts mode. It will now report errors + (about e.g. incorrect config files) instead of crashing + or hanging. Furthermore, the requirement that the test + directory name must have a "_test" suffix has been + removed. Also, a workaround has been implemented for the + limitation that the file browser (in many web browsers) + will only return the basic file name, not the full + directory path (which made it impossible to have config + files in other directories than the main test directory).</p> + <p> + Own Id: OTP-9429</p> + </item> + <item> + <p> + Add a proplist() type</p> + <p> + Recently I was adding specs to an API and found that + there is no canonical proplist() type defined. (Thanks to + Ryan Zezeski)</p> + <p> + Own Id: OTP-9499</p> + </item> + <item> + <p> + It is now possible to use the 'step' flag/option to run + the debugger for test suites that contain test case + groups. This previously caused Common Test to crash. If + 'step config' is specified, breakpoints are now also + automatically set on init_per_group and end_per_group. + Note that breakpoints are always set automatically on + test case functions and this is true also for grouped + cases.</p> + <p> + Own Id: OTP-9518 Aux Id: OTP-8933 </p> + </item> + <item> + <p> + The test index page was not refreshed at the start of + each test suite which made it impossible to follow test + execution by means of refreshing the browser window (no + links to follow). This has been fixed.</p> + <p> + Own Id: OTP-9520 Aux Id: OTP-8933 </p> + </item> + <item> + <p> + If a test suite would start with a test case group + defined without the init_per_group/2 and end_per_group/2 + function, init_per_suite/1 would not execute initially + and logging of the test run would fail. This error has + been fixed.</p> + <p> + Own Id: OTP-9584</p> + </item> + <item> + <p> + The "Missing Suites" link from the top level index page + was incorrect and has been fixed.</p> + <p> + Own Id: OTP-9592</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Various corrections and updates to improve the handling + and reporting of errors.</p> + <p> + Own Id: OTP-8933</p> + </item> + <item> + <p> + The dir and suite start option can now be used in + combination. E.g. executing my_SUITE in directory + my_tests can either be specified as "ct_run -suite + my_tests/my_SUITE" or as "ct_run -dir my_tests -suite + my_SUITE". Furthermore, the specification: + ct:run_test([{suite,["./my_SUITE"]},{testcase,t1}]) is + now interpreted as + ct:run_test([{suite,"./my_SUITE"},{testcase,t1}]), i.e. + only testcase t1 in test suite my_SUITE - not all cases - + will be executed.</p> + <p> + Own Id: OTP-9155</p> + </item> + <item> + <p> + A new option, 'logopts', has been introduced, to make it + possible to modify some aspects of the logging behaviour + in Common Test (or Test Server). For example, whenever an + io printout is made, test_server adds newline (\n) to the + end of the output string. This may not always be a + preferred action and can therefore be disabled by means + of "ct_run ... -logopts no_nl" (or ct:run_test([..., + {logopts,[no_nl]}])). A new framework callback function, + get_logopts/0, has been introduced (see the ct_framework + module for details).</p> + <p> + Own Id: OTP-9372 Aux Id: OTP-9396 </p> + </item> + <item> + <p> + A new option, 'logopts', has been introduced, to make it + possible to modify some aspects of the logging behaviour + in Common Test (or Test Server). For example, if the html + version of the test suite source code should not be + generated during the test run (and consequently be + unavailable in the log file system), the feature may be + disabled by means of "ct_run ... -logopts no_src" (or + ct:run_test([..., {logopts,[no_src]}])). A new framework + callback function, get_logopts/0, has been introduced + (see the ct_framework module for details).</p> + <p> + Own Id: OTP-9396 Aux Id: seq11869, OTP-9372 </p> + </item> + <item> + <p> + CT Hooks can now be assigned a priority. The priority of + a CTH determines when it should execute in relation to + other CTHs. The CTH with the lowest priority will be + executed first, CTHs with equal priority will be executed + in the order which they were installed.</p> + <p> + Own Id: OTP-9445</p> + </item> + <item> + <p> + It is now possible to use a tuple {M,F,A}, or a fun, as + timetrap specification in the suite info function or test + case info functions. The function must return a valid + timeout value, as documented in the common_test man page + and in the User's Guide.</p> + <p> + Own Id: OTP-9501 Aux Id: seq11894 </p> + </item> + <item> + <p> + A new built-in common test hook has been added which + captures error_logger and SASL event and prints them in + the testcase log. To disable this (and any other built-in + hooks) pass 'enable_builtin_hooks false' to common test.</p> + <p> + Own Id: OTP-9543</p> + </item> + <item> + <p> + Common Test now has the possibility to have built-in + hooks which are started by default when any test is run. + To disable built-in hooks pass 'enable_builtin_hooks + false' to common test. See the common test hooks + documentation for more details.</p> + <p> + Own Id: OTP-9564</p> + </item> + </list> + </section> + +</section> + <section><title>Common_Test 1.5.4</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/common_test/doc/src/part.xml b/lib/common_test/doc/src/part.xml index 3284bcadaa..a74185221d 100644 --- a/lib/common_test/doc/src/part.xml +++ b/lib/common_test/doc/src/part.xml @@ -65,6 +65,7 @@ </description> <xi:include href="basics_chapter.xml"/> + <xi:include href="getting_started_chapter.xml"/> <xi:include href="install_chapter.xml"/> <xi:include href="write_test_chapter.xml"/> <xi:include href="test_structure_chapter.xml"/> diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index e668568795..848f278fa6 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -128,6 +128,15 @@ <p><c>$ ct_run -suite $SYS1_TEST/setup_SUITE -case start stop</c></p> <p><c>$ ct_run -suite $SYS1_TEST/setup_SUITE -group installation -case start stop</c></p> + <p>It is also possible to combine the <c>dir</c>, <c>suite</c> and <c>group/case</c> flags. E.g, to run + <c>x_SUITE</c> and <c>y_SUITE</c> in directory <c>testdir</c>:</p> + + <p><c>$ ct_run -dir ./testdir -suite x_SUITE y_SUITE</c></p> + + <p>This has the same effect as calling:</p> + + <p><c>$ ct_run -suite ./testdir/x_SUITE ./testdir/y_SUITE</c></p> + <p>Other flags that may be used with <c>ct_run</c>:</p> <list> <item><c><![CDATA[-logdir <dir>]]></c>, specifies where the HTML log files are to be written.</item> @@ -150,6 +159,8 @@ <seealso marker="event_handler_chapter#event_handling">event handlers</seealso> including start arguments.</item> <item><c><![CDATA[-ct_hooks <ct_hooks>]]></c>, to install <seealso marker="ct_hooks_chapter#installing">Common Test Hooks</seealso> including start arguments.</item> + <item><c><![CDATA[-enable_builtin_hooks <bool>]]></c>, to enable/disable + <seealso marker="ct_hooks_chapter#builtin_cths">Built-in Common Test Hooks</seealso>. Default is <c>true</c>.</item> <item><c><![CDATA[-include]]></c>, specifies include directories (see above).</item> <item><c><![CDATA[-no_auto_compile]]></c>, disables the automatic test suite compilation feature (see above).</item> <item><c><![CDATA[-multiply_timetraps <n>]]></c>, extends <seealso marker="write_test_chapter#timetraps">timetrap @@ -165,6 +176,8 @@ <item><c><![CDATA[-decrypt_file <key_file>]]></c>, points out a file containing a decryption key for <seealso marker="config_file_chapter#encrypted_config_files">encrypted configuration files</seealso>.</item> <item><c><![CDATA[-basic_html]]></c>, switches off html enhancements that might not be compatible with older browsers.</item> + <item><c><![CDATA[-logopts <opts>]]></c>, makes it possible to modify aspects of the logging behaviour, see + <seealso marker="run_test_chapter#logopts">Log options</seealso> below.</item> </list> <note><p>Directories passed to Common Test may have either relative or absolute paths.</p></note> @@ -322,8 +335,9 @@ are to be executed by Common Test, and those functions only. If the step option <c>config</c> is specified, breakpoints will also be initially set on the configuration functions in the suite, i.e. - <c>init_per_suite/1</c>, <c>end_per_suite/1</c>, <c>init_per_testcase/2</c> - and <c>end_per_testcase/2</c>.</p> + <c>init_per_suite/1</c>, <c>end_per_suite/1</c>, + <c>init_per_group/2</c>, <c>end_per_group/2</c>, + <c>init_per_testcase/2</c> and <c>end_per_testcase/2</c>.</p> <p>Common Test enables the Debugger auto attach feature, which means that for every new interpreted test case function that starts to execute, a new trace window will automatically pop up. (This is because each test @@ -398,6 +412,16 @@ the way from <c>init_per_suite</c> down to the test cases in the sub group).</p> + <p>With the <c>GroupSpec</c> element (below) it's possible to specify + group execution properties that will override those specified in the + group definition (i.e. in <c>groups/0</c>). Execution properties for + sub-groups may be overridden as well. This feature makes it possible to + change properties of groups at the time of execution, + without even having to edit the test suite. More detailed documentation, + and examples, can be found in the + <seealso marker="write_test_chapter#test_case_groups"> + Test case groups</seealso> chapter.</p> + <p>Below is the test specification syntax. Test specifications can be used to run tests both in a single test host environment and in a distributed Common Test environment (Large Scale @@ -450,6 +474,8 @@ {ct_hooks, CTHModules}. {ct_hooks, NodeRefs, CTHModules}. + + {enable_builtin_hooks, Bool}. </pre> <p>Test terms:</p> <pre> @@ -459,8 +485,8 @@ {groups, DirRef, Suite, Groups}. {groups, NodeRefsDirRef, Suite, Groups}. - {groups, DirRef, Suite, Group, {cases,Cases}}. - {groups, NodeRefsDirRef, Suite, Group, {cases,Cases}}. + {groups, DirRef, Suite, GroupSpec, {cases,Cases}}. + {groups, NodeRefsDirRef, Suite, GroupSpec, {cases,Cases}}. {cases, DirRef, Suite, Cases}. {cases, NodeRefs, DirRef, Suite, Cases}. @@ -494,7 +520,8 @@ DirRef = DirAlias | Dir Suites = atom() | [atom()] | all Suite = atom() - Groups = atom() | [atom()] | all + Groups = GroupSpec | [GroupSpec] | all + GroupSpec = Group | {Group,Properties} | {Group,Properties,GroupSpec} Group = atom() Cases = atom() | [atom()] | all Comment = string() | "" @@ -628,10 +655,25 @@ to each individual test case log file for quick viewing with an HTML browser.</p> - <p>The minor log file contain full details of every single test - case, each one in a separate file. This way the files should - be easy to compare with previous test runs, even if the set of - test cases change.</p> + <p>The minor log files contain full details of every single test + case, each one in a separate file. This way, it should be + straightforward to compare the latest results to that of previous + test runs, even if the set of test cases changes. If SASL is running, + its logs will also be printed to the current minor log file by the + <seealso marker="common_test:ct_hooks_chapter#builtin_cths"> + cth_log_redirect built-in hook</seealso>. + </p> + + <p>The full name of the minor log file (i.e. the name of the file + including the absolute directory path) can be read during execution + of the test case. It comes as value in the tuple + <c>{tc_logfile,LogFileName}</c> in the <c>Config</c> list (which means it + can also be read by a pre- or post Common Test hook function). Also, + at the start of a test case, this data is sent with an event + to any installed event handler. Please see the + <seealso marker="event_handler_chapter#event_handling">Event Handling</seealso> + chapter for details. + </p> <p>Which information goes where is user configurable via the test server controller. Three threshold values determine what @@ -644,13 +686,44 @@ to follow test progress simply by refreshing pages in the HTML browser. Statistics totals are not presented until a test is complete however.</p> + <section> + <marker id="logopts"></marker> + <title>Log options</title> + <p>With the <c>logopts</c> start flag, it's possible to specify + options that modify some aspects of the logging behaviour. + Currently, the following options are available:</p> + <list> + <item><c>no_src</c></item> + <item><c>no_nl</c></item> + </list> + <p>With <c>no_src</c>, the html version of the test suite source + code will not be generated during the test run (and consequently + not be available in the log file system).</p> + <p>With <c>no_nl</c>, Common Test will not add a newline character + (\n) to the end of an output string that it receives from a call to e.g. + <c>io:format/2</c>, and which it prints to the test case log.</p> + <p>For example, if a test is started with:</p> + <p><c>$ ct_run -suite my_SUITE -logopts no_src</c></p> + <p>then printouts during the test made by successive calls to <c>io:format("x")</c>, + will appear in the test case log as:</p> + <p><c>xxx</c></p> + <p>instead of each <c>x</c> printed on a new line, which is the default behaviour.</p> + </section> + </section> <section> <marker id="html_stylesheet"></marker> <title>HTML Style Sheets</title> - <p>Common Test includes the <em>optional</em> feature to use - HTML style sheets (CSS) for customizing user printouts. The + <p>Common Test uses a CSS file to control the look of the HTML + files generated during test runs. If, for some reason, the + log files are not displayed correctly in the HTML browser of your + choice, or you prefer the "pre Common Test v1.6 look" + of the log files (i.e. not using CSS), use the start flag/option + <c>basic_html</c> to revert to the old style.</p> + + <p>Common Test includes an <em>optional</em> feature to allow + user HTML style sheets for customizing printouts. The functions in <c>ct</c> that print to a test case HTML log file (<c>log/3</c> and <c>pal/3</c>) accept <c>Category</c> as first argument. With this argument it's possible to @@ -664,22 +737,16 @@ look like this:</p> <pre> -<style> - div.ct_internal { background:lightgrey; color:black } - div.default { background:lightgreen; color:black } - div.sys_config { background:blue; color:white } - div.sys_state { background:yellow; color:black } - div.error { background:red; color:white } -</style> - </pre> + div.sys_config { background:blue; color:white } + div.sys_state { background:yellow; color:black } + div.error { background:red; color:white }</pre> <p>To install the CSS file (Common Test inlines the definition in the HTML code), the name may be provided when executing <c>ct_run</c>. Example:</p> <pre> - $ ct_run -dir $TEST/prog -stylesheet $TEST/styles/test_categories.css - </pre> + $ ct_run -dir $TEST/prog -stylesheet $TEST/styles/test_categories.css</pre> <p>Categories in a CSS file installed with the <c>-stylesheet</c> flag are on a global test level in the sense that they can be used in any @@ -700,8 +767,7 @@ ct:log(sys_state, "Connections: ~p", [ConnectionInfo]), ... ct:pal(error, "Error ~p detected! Info: ~p", [SomeFault,ErrorInfo]), - ct:fail(SomeFault). - </pre> + ct:fail(SomeFault).</pre> <p>If the style sheet is installed as in this example, the categories are private to the suite in question. They can be used by all test cases in the @@ -725,21 +791,6 @@ <p>The <c>Category</c> argument in the example above may have the value (atom) <c>sys_config</c> (white on blue), <c>sys_state</c> (black on yellow) or <c>error</c> (white on red).</p> - - <p>If the <c>Category</c> argument is not specified, Common Test will - use the CSS selector <c>div.default</c> for the - printout. For this reason a user supplied style sheet must - include this selector. Also the selector - <c>div.ct_internal</c> must be included. Hence a minimal - user style sheet should look like this (which is also the - default style sheet Common Test uses if no user CSS file is - provided):</p> - <pre> - <style> - div.ct_internal { background:lightgrey; color:black } - div.default { background:lightgreen; color:black } - </style> - </pre> </section> <section> diff --git a/lib/common_test/doc/src/tc_execution.gif b/lib/common_test/doc/src/tc_execution.gif Binary files differnew file mode 100644 index 0000000000..7c89d7be57 --- /dev/null +++ b/lib/common_test/doc/src/tc_execution.gif diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml index 3f9fdb7121..c0ec26ddcc 100644 --- a/lib/common_test/doc/src/write_test_chapter.xml +++ b/lib/common_test/doc/src/write_test_chapter.xml @@ -68,7 +68,7 @@ <p>Each test suite module must export the function <c>all/0</c> which returns the list of all test case groups and test cases - in that module. + to be executed in that module. </p> </section> @@ -280,6 +280,8 @@ the timetrap time is exceeded, the test case fails with reason <c>timetrap_timeout</c>. Note that <c>init_per_testcase</c> and <c>end_per_testcase</c> are included in the timetrap time. + Please see the <seealso marker="write_test_chapter#timetraps">Timetrap</seealso> + section for more details. </p> </item> <tag><em><c>userdata</c></em></tag> @@ -367,10 +369,12 @@ <title>Test suite info function</title> <p>The <c>suite/0</c> function can be used in a test suite - module to set the default values for the <c>timetrap</c> and - <c>require</c> tags. If a test case info function also specifies - any of these tags, the default value is overruled. See above for - more information. + module to e.g. set a default <c>timetrap</c> value and to + <c>require</c> external configuration data. If a test case-, or + group info function also specifies any of the info tags, it + overrides the default values set by <c>suite/0</c>. See the test + case info function above, and group info function below, for more + details. </p> <p>Other options that may be specified with the suite info list are:</p> @@ -448,11 +452,65 @@ <pre> all() -> [testcase1, {group,group1}, testcase2, {group,group2}].</pre> - <p>Properties may be combined so that e.g. if <c>shuffle</c>, - <c>repeat_until_any_fail</c> and <c>sequence</c> are all specified, the test - cases in the group will be executed repeatedly and in random order until - a test case fails, when execution is immediately stopped and the rest of - the cases skipped.</p> + <p>It is also possible to specify execution properties with a group + tuple in <c>all/0</c>: <c>{group,GroupName,Properties}</c>. These + properties will override those specified in the group definition (see + <c>groups/0</c> above). This way, it's possible to run the same set of tests, + but with different properties, without having to make copies of the group + definition in question.</p> + + <p>If a group contains sub-groups, the execution properties for these may + also be specified in the group tuple: + <c>{group,GroupName,Properties,SubGroups}</c>, where <c>SubGroups</c> + is a list of tuples, <c>{GroupName,Properties}</c>, or + <c>{GroupName,Properties,SubGroups}</c>, representing the sub-groups. + Any sub-groups defined in <c>group/0</c> for a group, that are not specified + in the <c>SubGroups</c> list, will simply execute with their pre-defined + properties.</p> + + <p>Example:</p> + <pre> + groups() -> {tests1, [], [{tests2, [], [t2a,t2b]}, + {tests3, [], [t31,t3b]}]}.</pre> + <p>To execute group 'tests1' twice with different properties for 'tests2' + each time:</p> + <pre> + all() -> + [{group, tests1, default, [{tests2, [parallel]}]}, + {group, tests1, default, [{tests2, [shuffle,{repeat,10}]}]}].</pre> + <p>Note that this is equivalent to this specification:</p> + <pre> + all() -> + [{group, tests1, default, [{tests2, [parallel]}, + {tests3, default}]}, + {group, tests1, default, [{tests2, [shuffle,{repeat,10}]}, + {tests3, default}]}].</pre> + <p>The value <c>default</c> states that the pre-defined properties + should be used.</p> + <p>Here's an example of how to override properties in a scenario + with deeply nested groups:</p> + <pre> + groups() -> + [{tests1, [], [{group, tests2}]}, + {tests2, [], [{group, tests3}]}, + {tests3, [{repeat,2}], [t3a,t3b,t3c]}]. + + all() -> + [{group, tests1, default, + [{tests2, default, + [{tests3, [parallel,{repeat,100}]}]}]}].</pre> + + <p>The syntax described above may also be used in Test Specifications + in order to change properties of groups at the time of execution, + without even having to edit the test suite (please see the + <seealso marker="run_test_chapter#test_specifications">Test + Specifications</seealso> chapter for more info).</p> + + <p>As illustrated above, properties may be combined. If e.g. + <c>shuffle</c>, <c>repeat_until_any_fail</c> and <c>sequence</c> + are all specified, the test cases in the group will be executed + repeatedly, and in random order, until a test case fails. Then + execution is immediately stopped and the rest of the cases skipped.</p> <p>Before execution of a group begins, the configuration function <c>init_per_group(GroupName, Config)</c> is called (the function is @@ -639,6 +697,51 @@ </section> <section> + <marker id="group_info"></marker> + <title>Group info function</title> + + <p>The test case group info function, <c>group(GroupName)</c>, + serves the same purpose as the suite- and test case info + functions previously described in this chapter. The scope for + the group info, however, is all test cases and sub-groups in the + group in question (<c>GroupName</c>).</p> + <p>Example:</p> + <pre> + group(connection_tests) -> + [{require,login_data}, + {timetrap,1000}].</pre> + + <p>The group info properties override those set with the + suite info function, and may in turn be overridden by test + case info properties. Please see the test case info + function above for a list of valid info properties and more + general information.</p> + </section> + + <section> + <title>Info functions for init- and end-configuration</title> + <p>It is possible to use info functions also for the <c>init_per_suite</c>, + <c>end_per_suite</c>, <c>init_per_group</c>, and <c>end_per_group</c> + functions, and it works the same way as with info functions + for test cases (see above). This is useful e.g. for setting + timetraps and requiring external configuration data relevant + only for the configuration function in question (without + affecting properties set for groups and test cases in the suite).</p> + + <p>The info function <c>init/end_per_suite()</c> is called for + <c>init/end_per_suite(Config)</c>, and info function + <c>init/end_per_group(GroupName)</c> is called for + <c>init/end_per_group(GroupName,Config)</c>. Info functions + can not be used with <c>init/end_per_testcase(TestCase, Config)</c>, + however, since these configuration functions execute on the test case process + and will use the same properties as the test case (i.e. the properties + set by the test case info function, <c>TestCase()</c>). Please see the test case + info function above for a list of valid info properties and more + general information. + </p> + </section> + + <section> <marker id="data_priv_dir"></marker> <title>Data and Private Directories</title> @@ -699,8 +802,8 @@ </section> <section> - <title>Timetrap timeouts</title> <marker id="timetraps"></marker> + <title>Timetrap timeouts</title> <p>The default time limit for a test case is 30 minutes, unless a <c>timetrap</c> is specified either by the suite info function or a test case info function. The timetrap timeout value defined @@ -723,6 +826,13 @@ multipled by <c>multiply_timetraps</c>, and possibly scaled up if <c>scale_timetraps</c> is enabled, the function <c>ct:sleep/1</c> may be called.</p> + <p>A function (<c>fun</c> or <c>MFA</c>) may be specified as timetrap value + in the suite- and test case info function, e.g:</p> + <p><c>{timetrap,{test_utils,get_timetrap_value,[?MODULE,system_start]}}</c></p> + <p>The function will be called initially by Common Test (before execution + of the suite or the test case) and must return a time value such as an + integer (millisec), or a <c>{SecMinOrHourTag,Time}</c> tuple. More + information can be found in the <c>common_test</c> reference manual.</p> </section> <section> @@ -818,6 +928,3 @@ </list> </section> </chapter> - - - diff --git a/lib/common_test/include/ct.hrl b/lib/common_test/include/ct.hrl index aa1cc832cf..5a77108e1a 100644 --- a/lib/common_test/include/ct.hrl +++ b/lib/common_test/include/ct.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2011. 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 @@ -18,5 +18,4 @@ %% -include_lib("test_server/include/test_server.hrl"). --compile({parse_transform,ct_line}). diff --git a/lib/common_test/priv/Makefile.in b/lib/common_test/priv/Makefile.in index f4a0c181f9..d9033f6ef1 100644 --- a/lib/common_test/priv/Makefile.in +++ b/lib/common_test/priv/Makefile.in @@ -59,6 +59,7 @@ ifneq ($(findstring win32,$(TARGET)),win32) FILES = vts.tool SCRIPTS = IMAGES = tile1.jpg +CSS = ct_default.css # # Rules @@ -85,11 +86,11 @@ include $(ERL_TOP)/make/otp_release_targets.mk ifeq ($(XNIX),true) release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/priv - $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv + $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(RELSYSDIR)/priv else release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/priv - $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv + $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(RELSYSDIR)/priv endif release_docs_spec: @@ -105,6 +106,7 @@ else # FILES = vts.tool IMAGES = tile1.jpg +CSS = ct_default.css # # Rules @@ -124,7 +126,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/priv - $(INSTALL_DATA) $(FILES) $(IMAGES) $(RELSYSDIR)/priv + $(INSTALL_DATA) $(FILES) $(IMAGES) $(CSS) $(RELSYSDIR)/priv release_docs_spec: diff --git a/lib/common_test/priv/auxdir/config.guess b/lib/common_test/priv/auxdir/config.guess index fefabd7dd0..38a833903b 120000..100755 --- a/lib/common_test/priv/auxdir/config.guess +++ b/lib/common_test/priv/auxdir/config.guess @@ -1 +1,1519 @@ -../../../../erts/autoconf/config.guess
\ No newline at end of file +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-05-17' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner <[email protected]>. +# Please send patches to <[email protected]>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <[email protected]>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# ([email protected] 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # [email protected] (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile:Linux:*:*) + echo tile-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa:Linux:*:*) + echo xtensa-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <[email protected]> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <[email protected]>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From [email protected]. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From [email protected]. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From [email protected]. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess +and + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <[email protected]> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/lib/common_test/priv/auxdir/config.sub b/lib/common_test/priv/auxdir/config.sub index 90979e8924..f43233b104 120000..100755 --- a/lib/common_test/priv/auxdir/config.sub +++ b/lib/common_test/priv/auxdir/config.sub @@ -1 +1,1630 @@ -../../../../erts/autoconf/config.sub
\ No newline at end of file +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-04-29' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <[email protected]>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <[email protected]>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tile*) + basic_machine=tile-tilera + os=-linux-gnu + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/lib/common_test/priv/auxdir/install-sh b/lib/common_test/priv/auxdir/install-sh index 9422c370df..a5897de6ea 120000..100755 --- a/lib/common_test/priv/auxdir/install-sh +++ b/lib/common_test/priv/auxdir/install-sh @@ -1 +1,519 @@ -../../../../erts/autoconf/install-sh
\ No newline at end of file +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2006-12-25.00 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/lib/common_test/priv/ct_default.css b/lib/common_test/priv/ct_default.css new file mode 100644 index 0000000000..75f8d5db8a --- /dev/null +++ b/lib/common_test/priv/ct_default.css @@ -0,0 +1,186 @@ +/* Stylesheet for Common Test */ + +body { + padding: 10px; margin: 10px; + -webkit-font-smoothing: antialiased; + background-color: #FBFFFC; +} + +a:link { + color: #2B507D; +} + +a:visited { + color: #85ABD5 +} + +h1 { + font-family: verdana, arial, sans-serif; font-size: 200%; + letter-spacing: -2px; word-spacing: 2px; font-weight: bold; + color: #3F3F3F; +} + +h2 { + font-family: verdana, arial, sans-serif; font-size: 175%; + letter-spacing: -2px; word-spacing: 2px; font-weight: normal; + color: #3F3F3F; +} + +h3 { + font-family: verdana, arial, sans-serif; font-size: 140%; + letter-spacing: -2px; word-spacing: 2px; font-weight: bold; + color: #3F3F3F; +} + +h4 { + font-family: verdana, arial, sans-serif; font-size: 120%; + letter-spacing: -2px; word-spacing: 2px; font-weight: normal; + color: #3F3F3F; +} + +p { + font-family: "Trebuchet MS", "Lucida Sans Unicode", verdana, arial, sans-serif; + font-size: .9em; color: #000000; +} + +ul { + list-style-type: none; + padding: 0em; + margin: 1em; +} +li { + font-size: 0.95em; color: #000000; + margin: .3em 0; +} + +pre { + color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: .8em; + } + +code { + color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: .8em; +} + +div.mono_sm { + font-family: "Courier New", monospace; font-size: .75em; + word-spacing: 1px; color: #000000; +} + +div.mono_la { + font-family: "Courier New", monospace; font-size: .8em; + color: #000000; +} + +div.copyright { + padding: 20px 0px 0px 0px; + font-family: "Courier New", monospace; font-size: .7em; + color: #000000; +} + +div.ct_internal { + background: lightgrey; color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: .95em; + margin: .2em 0 0 0; +} + +div.default { + background: lightgreen; color: black; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: 1.05em; + margin: .2em 0 0 0; +} + +div.label { + font-family: verdana, arial, sans-serif; font-size: 200%; + letter-spacing: -2.5px; word-spacing: 2px; + font-weight: bold; color: #2B507D; +} + +table { + border-collapse: collapse; border: 6px solid #3F3F3F; + background: #FFFFFF; + font: .8em/1.2em "Lucida Sans Unicode", verdana, arial, sans-serif; + color: #222; +} + +caption { + font-size: 1.3em; font-weight: bold; + text-align: center; padding: 1em 4px; +} + +td, th { + padding: .5em 7px .5em 7px; line-height: 1.3em; + border-bottom: 3px solid #F5C4C1; + border-left: 2px dashed #809FFF; +} + +th { + background: #3F3F3F; color: #fff; + font-family: arial, sans-serif; font-size: 120%; + letter-spacing: -0.5px; + font-weight: bold; text-align: center; + padding-right: .5em; vertical-align: top; +} + +thead th { + background: #2C5755; text-align: center; +} + +.odd td { + background: #F3F3F3; +} +.odd th { + background: #F3F3F3; +} + +td a, td a:link { + color: #2B507D; +} + +td a:visited { + color: #85ABD5; +} + +tr:hover th[scope=row], tr:hover td { + background-color: #D1D1D1; + color: #fff; +} + +td a:hover, td a:focus { + color: #85ABD5; +} + +th a, td a:active { + color: #85ABD5; +} + +tfoot th, tfoot td { + background: #3F3F3F; color: #fff; +} + +th + td { + padding-left: .5em; +} + +#button_holder { + display: block; float: center; + font-family: arial, verdana, sans-serif; + font-size: 12px; text-shadow: 1px 1px lightgray; +} + +.btn a { + padding: 6px 12px; float: center; + text-decoration: none; color: #3F3F3F; + font-weight: bold; border: 3px outset #3F3F3F; + background-color: #F3F3F3; +} + +.btn a:hover { + color: #fff; + background-color: #809FFF; +} diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile index 84b122b5e4..125aa828fb 100644 --- a/lib/common_test/src/Makefile +++ b/lib/common_test/src/Makefile @@ -40,7 +40,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/common_test-$(VSN) # ---------------------------------------------------- MODULES= \ - ct_line \ ct \ ct_logs \ ct_framework \ @@ -69,9 +68,11 @@ MODULES= \ ct_config_xml \ ct_slave \ ct_hooks\ - ct_hooks_lock + ct_hooks_lock\ + cth_log_redirect TARGET_MODULES= $(MODULES:%=$(EBIN)/%) +BEAM_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) ERL_FILES= $(MODULES:=.erl) HRL_FILES = \ @@ -97,7 +98,7 @@ ERL_COMPILE_FLAGS += -pa ../ebin -I../include -I $(ERL_TOP)/lib/snmp/include/ \ # ---------------------------------------------------- TARGET_FILES = \ $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \ - $(MODULES:%=$(EBIN)/%.$(EMULATOR)) \ + $(BEAM_FILES) \ $(APP_TARGET) $(APPUP_TARGET) APP_FILE= common_test.app diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src index b42173f412..7fba484b18 100644 --- a/lib/common_test/src/common_test.app.src +++ b/lib/common_test/src/common_test.app.src @@ -1,7 +1,7 @@ % This is an -*- erlang -*- file. %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2010. All Rights Reserved. +%% Copyright Ericsson AB 2009-2011. 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 @@ -25,7 +25,6 @@ ct_framework, ct_ftp, ct_gen_conn, - ct_line, ct_logs, ct_make, ct_master, diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 66da3ef742..e0e82283c4 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -63,9 +63,10 @@ log/1, log/2, log/3, print/1, print/2, print/3, pal/1, pal/2, pal/3, - fail/1, comment/1, + capture_start/0, capture_stop/0, capture_get/0, capture_get/1, + fail/1, fail/2, comment/1, comment/2, testcases/2, userdata/2, userdata/3, - timetrap/1, sleep/1]). + timetrap/1, get_timetrap_info/0, sleep/1]). %% New API for manipulating with config handlers -export([add_config/2, remove_config/2]). @@ -108,7 +109,7 @@ install(Opts) -> %%% Cases = atom() | [atom()] %%% Result = [TestResult] | {error,Reason} %%% -%%% @doc Run the given testcase(s). +%%% @doc Run the given test case(s). %%% %%% <p>Requires that <code>ct:install/1</code> has been run first.</p> %%% @@ -121,7 +122,7 @@ run(TestDir,Suite,Cases) -> %%%----------------------------------------------------------------- %%% @spec run(TestDir,Suite) -> Result %%% -%%% @doc Run all testcases in the given suite. +%%% @doc Run all test cases in the given suite. %%% @see run/3. run(TestDir,Suite) -> ct_run:run(TestDir,Suite). @@ -130,7 +131,7 @@ run(TestDir,Suite) -> %%% @spec run(TestDirs) -> Result %%% TestDirs = TestDir | [TestDir] %%% -%%% @doc Run all testcases in all suites in the given directories. +%%% @doc Run all test cases in all suites in the given directories. %%% @see run/3. run(TestDirs) -> ct_run:run(TestDirs). @@ -148,10 +149,10 @@ run(TestDirs) -> %%% {auto_compile,Bool} | {multiply_timetraps,M} | {scale_timetraps,Bool} | %%% {repeat,N} | {duration,DurTime} | {until,StopTime} | %%% {force_stop,Bool} | {decrypt,DecryptKeyOrFile} | -%%% {refresh_logs,LogDir} | {basic_html,Bool} | -%%% {ct_hooks, CTHs} +%%% {refresh_logs,LogDir} | {logopts,LogOpts} | {basic_html,Bool} | +%%% {ct_hooks, CTHs} | {enable_builtin_hooks,Bool} %%% TestDirs = [string()] | string() -%%% Suites = [string()] | string() +%%% Suites = [string()] | [atom()] | string() | atom() %%% Cases = [atom()] | atom() %%% Groups = [atom()] | atom() %%% TestSpecs = [string()] | string() @@ -177,6 +178,8 @@ run(TestDirs) -> %%% DecryptKeyOrFile = {key,DecryptKey} | {file,DecryptFile} %%% DecryptKey = string() %%% DecryptFile = string() +%%% LogOpts = [LogOpt] +%%% LogOpt = no_nl | no_src %%% CTHs = [CTHModule | {CTHModule, CTHInitArgs}] %%% CTHModule = atom() %%% CTHInitArgs = term() @@ -438,11 +441,10 @@ log(X1,X2) -> %%% Format = string() %%% Args = list() %%% -%%% @doc Printout from a testcase to the log. +%%% @doc Printout from a test case to the log file. %%% -%%% <p>This function is meant for printing stuff directly from a -%%% testcase (i.e. not from within the CT framework) in the test -%%% log.</p> +%%% <p>This function is meant for printing a string directly from a +%%% test case to the test case log file.</p> %%% %%% <p>Default <code>Category</code> is <code>default</code> and %%% default <code>Args</code> is <code>[]</code>.</p> @@ -471,10 +473,10 @@ print(X1,X2) -> %%% Format = string() %%% Args = list() %%% -%%% @doc Printout from a testcase to the console. +%%% @doc Printout from a test case to the console. %%% -%%% <p>This function is meant for printing stuff from a testcase on -%%% the console.</p> +%%% <p>This function is meant for printing a string from a test case +%%% to the console.</p> %%% %%% <p>Default <code>Category</code> is <code>default</code> and %%% default <code>Args</code> is <code>[]</code>.</p> @@ -506,16 +508,75 @@ pal(X1,X2) -> %%% Format = string() %%% Args = list() %%% -%%% @doc Print and log from a testcase. +%%% @doc Print and log from a test case. %%% -%%% <p>This function is meant for printing stuff from a testcase both -%%% in the log and on the console.</p> +%%% <p>This function is meant for printing a string from a test case, +%%% both to the test case log file and to the console.</p> %%% %%% <p>Default <code>Category</code> is <code>default</code> and %%% default <code>Args</code> is <code>[]</code>.</p> pal(Category,Format,Args) -> ct_logs:tc_pal(Category,Format,Args). +%%%----------------------------------------------------------------- +%%% @spec capture_start() -> ok +%%% +%%% @doc Start capturing all text strings printed to stdout during +%%% execution of the test case. +%%% +%%% @see capture_stop/0 +%%% @see capture_get/1 +capture_start() -> + test_server:capture_start(). + +%%%----------------------------------------------------------------- +%%% @spec capture_stop() -> ok +%%% +%%% @doc Stop capturing text strings (a session started with +%%% <code>capture_start/0</code>). +%%% +%%% @see capture_start/0 +%%% @see capture_get/1 +capture_stop() -> + test_server:capture_stop(). + +%%%----------------------------------------------------------------- +%%% @spec capture_get() -> ListOfStrings +%%% ListOfStrings = [string()] +%%% +%%% @equiv capture_get([default]) +capture_get() -> + %% remove default log printouts (e.g. ct:log/2 printouts) + capture_get([default]). + +%%%----------------------------------------------------------------- +%%% @spec capture_get(ExclCategories) -> ListOfStrings +%%% ExclCategories = [atom()] +%%% ListOfStrings = [string()] +%%% +%%% @doc Return and purge the list of text strings buffered +%%% during the latest session of capturing printouts to stdout. +%%% With <code>ExclCategories</code> it's possible to specify +%%% log categories that should be ignored in <code>ListOfStrings</code>. +%%% If <code>ExclCategories = []</code>, no filtering takes place. +%%% +%%% @see capture_start/0 +%%% @see capture_stop/0 +%%% @see log/3 +capture_get([ExclCat | ExclCategories]) -> + Strs = test_server:capture_get(), + CatsStr = [atom_to_list(ExclCat) | + [[$| | atom_to_list(EC)] || EC <- ExclCategories]], + {ok,MP} = re:compile("<div class=\"(" ++ lists:flatten(CatsStr) ++ ")\">.*"), + lists:flatmap(fun(Str) -> + case re:run(Str, MP) of + {match,_} -> []; + nomatch -> [Str] + end + end, Strs); + +capture_get([]) -> + test_server:capture_get(). %%%----------------------------------------------------------------- %%% @spec fail(Reason) -> void() @@ -526,18 +587,35 @@ pal(Category,Format,Args) -> fail(Reason) -> exit({test_case_failed,Reason}). + +%%%----------------------------------------------------------------- +%%% @spec fail(Format, Args) -> void() +%%% Format = string() +%%% Args = list() +%%% +%%% @doc Terminate a test case with an error message specified +%%% by a format string and a list of values (used as arguments to +%%% <code>io_lib:format/2</code>). +fail(Format, Args) -> + try io_lib:format(Format, Args) of + Str -> + exit({test_case_failed,lists:flatten(Str)}) + catch + _:BadArgs -> + exit({BadArgs,{?MODULE,fail,[Format,Args]}}) + end. + + %%%----------------------------------------------------------------- %%% @spec comment(Comment) -> void() %%% Comment = term() %%% -%%% @doc Print the given <code>Comment</code> in the comment field of +%%% @doc Print the given <code>Comment</code> in the comment field in %%% the table on the test suite result page. %%% %%% <p>If called several times, only the last comment is printed. -%%% <code>comment/1</code> is also overwritten by the return value -%%% <code>{comment,Comment}</code> or by the function -%%% <code>fail/1</code> (which prints <code>Reason</code> as a -%%% comment).</p> +%%% The test case return value <code>{comment,Comment}</code> +%%% overwrites the string set by this function.</p> comment(Comment) when is_list(Comment) -> Formatted = case (catch io_lib:format("~s",[Comment])) of @@ -551,6 +629,29 @@ comment(Comment) -> Formatted = io_lib:format("~p",[Comment]), send_html_comment(lists:flatten(Formatted)). +%%%----------------------------------------------------------------- +%%% @spec comment(Format, Args) -> void() +%%% Format = string() +%%% Args = list() +%%% +%%% @doc Print the formatted string in the comment field in +%%% the table on the test suite result page. +%%% +%%% <p>The <code>Format</code> and <code>Args</code> arguments are +%%% used in call to <code>io_lib:format/2</code> in order to create +%%% the comment string. The behaviour of <code>comment/2</code> is +%%% otherwise the same as the <code>comment/1</code> function (see +%%% above for details).</p> +comment(Format, Args) when is_list(Format), is_list(Args) -> + Formatted = + case (catch io_lib:format(Format, Args)) of + {'EXIT',Reason} -> % bad args + exit({Reason,{?MODULE,comment,[Format,Args]}}); + String -> + lists:flatten(String) + end, + send_html_comment(Formatted). + send_html_comment(Comment) -> Html = "<font color=\"green\">" ++ Comment ++ "</font>", ct_util:set_testdata({comment,Html}), @@ -604,7 +705,7 @@ listenv(Telnet) -> %%% Testcases = list() %%% Reason = term() %%% -%%% @doc Returns all testcases in the specified suite. +%%% @doc Returns all test cases in the specified suite. testcases(TestDir, Suite) -> case make_and_load(TestDir, Suite) of E = {error,_} -> @@ -662,7 +763,8 @@ userdata(TestDir, Suite) -> get_userdata(Info, "suite/0") end. -get_userdata({'EXIT',{undef,_}}, Spec) -> +get_userdata({'EXIT',{Undef,_}}, Spec) when Undef == undef; + Undef == function_clause -> {error,list_to_atom(Spec ++ " is not defined")}; get_userdata({'EXIT',Reason}, Spec) -> {error,{list_to_atom("error in " ++ Spec),Reason}}; @@ -678,16 +780,27 @@ get_userdata(_BadTerm, Spec) -> {error,list_to_atom(Spec ++ " must return a list")}. %%%----------------------------------------------------------------- -%%% @spec userdata(TestDir, Suite, Case) -> TCUserData | {error,Reason} +%%% @spec userdata(TestDir, Suite, GroupOrCase) -> TCUserData | {error,Reason} %%% TestDir = string() %%% Suite = atom() -%%% Case = atom() +%%% GroupOrCase = {group,GroupName} | atom() +%%% GroupName = atom() %%% TCUserData = [term()] %%% Reason = term() %%% %%% @doc Returns any data specified with the tag <code>userdata</code> -%%% in the list of tuples returned from <code>Suite:Case/0</code>. -userdata(TestDir, Suite, Case) -> +%%% in the list of tuples returned from <code>Suite:group(GroupName)</code> +%%% or <code>Suite:Case()</code>. +userdata(TestDir, Suite, {group,GroupName}) -> + case make_and_load(TestDir, Suite) of + E = {error,_} -> + E; + _ -> + Info = (catch apply(Suite, group, [GroupName])), + get_userdata(Info, "group("++atom_to_list(GroupName)++")") + end; + +userdata(TestDir, Suite, Case) when is_atom(Case) -> case make_and_load(TestDir, Suite) of E = {error,_} -> E; @@ -865,6 +978,18 @@ timetrap(Time) -> test_server:timetrap(Time). %%%----------------------------------------------------------------- +%%% @spec get_timetrap_info() -> {Time,Scale} +%%% Time = integer() | infinity +%%% Scale = true | false +%%% +%%% @doc <p>Read info about the timetrap set for the current test case. +%%% <c>Scale</c> indicates if Common Test will attempt to automatically +%%% compensate timetraps for runtime delays introduced by e.g. tools like +%%% cover.</p> +get_timetrap_info() -> + test_server:get_timetrap_info(). + +%%%----------------------------------------------------------------- %%% @spec sleep(Time) -> ok %%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity %%% Hours = integer() diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl index 6b75937668..9277af5bc1 100644 --- a/lib/common_test/src/ct_config.erl +++ b/lib/common_test/src/ct_config.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2011. 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 @@ -204,9 +204,9 @@ get_config_file_list(Opts) -> DefaultConfigs = process_default_configs(Opts), CfgFiles = if - DefaultConfigs == []-> + DefaultConfigs == [] -> []; - true-> + true -> [{?ct_config_txt, DefaultConfigs}] end ++ process_user_configs(Opts, []), @@ -240,12 +240,12 @@ read_config_files(Opts) -> end, ConfigFiles = case lists:keyfind(config, 1, Opts) of - {config,ConfigLists}-> + {config,ConfigLists} -> lists:foldr(fun({Callback,Files}, Acc) -> AddCallback(Callback,Files) ++ Acc end,[],ConfigLists); - false-> + false -> [] end, read_config_files_int(ConfigFiles, fun store_config/3). @@ -255,7 +255,9 @@ read_config_files_int([{Callback, File}|Files], FunToSave) -> {ok, Config} -> FunToSave(Config, Callback, File), read_config_files_int(Files, FunToSave); - {error, ErrorName, ErrorDetail}-> + {error, {ErrorName, ErrorDetail}} -> + {user_error, {ErrorName, File, ErrorDetail}}; + {error, ErrorName, ErrorDetail} -> {user_error, {ErrorName, File, ErrorDetail}} end; read_config_files_int([], _FunToSave) -> @@ -283,7 +285,7 @@ rewrite_config(Config, Callback, File) -> config=File,_='_'}), Updater = fun({Key, Value}) -> case keyfindall(Key, #ct_conf.key, OldRows) of - []-> + [] -> ets:insert(?attr_table, #ct_conf{key=Key, value=Value, @@ -453,9 +455,9 @@ update_conf(Name, NewConfig) -> reload_conf(KeyOrName) -> case lookup_handler_for_config(KeyOrName) of - []-> + [] -> undefined; - HandlerList-> + HandlerList -> HandlerList2 = lists:usort(HandlerList), read_config_files_int(HandlerList2, fun rewrite_config/3), get_config(KeyOrName) @@ -711,13 +713,13 @@ random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]). check_callback_load(Callback) -> case code:is_loaded(Callback) of - {file, _Filename}-> + {file, _Filename} -> check_exports(Callback); - false-> + false -> case code:load_file(Callback) of - {module, Callback}-> + {module, Callback} -> check_exports(Callback); - {error, Error}-> + {error, Error} -> {error, Error} end end. @@ -745,14 +747,14 @@ check_config_files(Configs) -> end, Files) end; - {error, Why}-> + {error, Why} -> {error, {callback, {Callback,Why}}} end; ({Callback, []}) -> case check_callback_load(Callback) of - {ok, Callback}-> + {ok, Callback} -> Callback:check_parameter([]); - {error, Why}-> + {error, Why} -> {error, {callback, {Callback,Why}}} end end, @@ -773,15 +775,15 @@ prepare_user_configs([], Acc, _) -> prepare_config_list(Args) -> ConfigFiles = case lists:keysearch(ct_config, 1, Args) of - {value,{ct_config,Files}}-> + {value,{ct_config,Files}} -> [{?ct_config_txt,[filename:absname(F) || F <- Files]}]; - false-> + false -> [] end, UserConfigs = case lists:keysearch(userconfig, 1, Args) of - {value,{userconfig,UserConfigFiles}}-> + {value,{userconfig,UserConfigFiles}} -> prepare_user_configs(UserConfigFiles, [], new); - false-> + false -> [] end, ConfigFiles ++ UserConfigs. diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl index 3fbc8af9fb..237df5c8f3 100644 --- a/lib/common_test/src/ct_config_plain.erl +++ b/lib/common_test/src/ct_config_plain.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2011. 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 @@ -29,7 +29,7 @@ read_config(ConfigFile) -> {ok,Config} -> {ok, Config}; {error,enoent} -> - {error, config_file_error, enoent}; + {error,{config_file_error,file:format_error(enoent)}}; {error,Reason} -> Key = case application:get_env(common_test, decrypt) of @@ -45,23 +45,27 @@ read_config(ConfigFile) -> end, case Key of {error,no_crypt_file} -> - {error, config_file_error, Reason}; + {error,{config_file_error, + lists:flatten( + io_lib:format("~s",[file:format_error(Reason)]))}}; {error,CryptError} -> - {error, decrypt_file_error, CryptError}; + {error,{decrypt_file_error,CryptError}}; _ when is_list(Key) -> - case ct_config:decrypt_config_file(ConfigFile, undefined, {key,Key}) of + case ct_config:decrypt_config_file(ConfigFile, + undefined, + {key,Key}) of {ok,CfgBin} -> case read_config_terms(CfgBin) of {error,ReadFail} -> - {error, config_file_error, ReadFail}; + {error,{config_file_error,ReadFail}}; Config -> - {ok, Config} + {ok,Config} end; {error,DecryptFail} -> - {error, decrypt_config_error, DecryptFail} + {error,{decrypt_config_error,DecryptFail}} end; _ -> - {error, bad_decrypt_key, Key} + {error,{bad_decrypt_key,Key}} end end. @@ -69,9 +73,9 @@ read_config(ConfigFile) -> check_parameter(File)-> case filelib:is_file(File) of true-> - {ok, {file, File}}; + {ok,{file,File}}; false-> - {error, {nofile, File}} + {error,{nofile,File}} end. read_config_terms(Bin) when is_binary(Bin) -> diff --git a/lib/common_test/src/ct_config_xml.erl b/lib/common_test/src/ct_config_xml.erl index 8a6e75e635..6e0a016161 100644 --- a/lib/common_test/src/ct_config_xml.erl +++ b/lib/common_test/src/ct_config_xml.erl @@ -1,7 +1,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2011. 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 @@ -27,30 +27,30 @@ % read config file read_config(ConfigFile) -> case catch do_read_xml_config(ConfigFile) of - {ok, Config}-> - {ok, Config}; - {error, Error, ErroneousString}-> - {error, Error, ErroneousString} + {ok,Config} -> + {ok,Config}; + Error = {error,_} -> + Error end. % check file exists -check_parameter(File)-> +check_parameter(File) -> case filelib:is_file(File) of - true-> - {ok, {file, File}}; - false-> - {error, {nofile, File}} + true -> + {ok,{file,File}}; + false -> + {error,{nofile,File}} end. % actual reading of the config -do_read_xml_config(ConfigFile)-> +do_read_xml_config(ConfigFile) -> case catch xmerl_sax_parser:file(ConfigFile, - [{event_fun, fun event/3}, - {event_state, []}]) of - {ok, EntityList, _}-> - {ok, lists:reverse(transform_entity_list(EntityList))}; - Oops-> - {error, parsing_failed, Oops} + [{event_fun,fun event/3}, + {event_state,[]}]) of + {ok,EntityList,_} -> + {ok,lists:reverse(transform_entity_list(EntityList))}; + Oops -> + {error,{parsing_failed,Oops}} end. % event callback for xmerl_sax_parser @@ -92,18 +92,18 @@ tag(_El, State) -> State. % transform of the ugly deeply nested entity list to the key-value "tree" -transform_entity_list(EntityList)-> +transform_entity_list(EntityList) -> lists:map(fun transform_entity/1, EntityList). % transform entity from {list(), list()} to {atom(), term()} transform_entity({Tag, [Value|Rest]}) when - is_tuple(Value)-> + is_tuple(Value) -> {list_to_atom(Tag), transform_entity_list(lists:reverse([Value|Rest]))}; -transform_entity({Tag, String})-> +transform_entity({Tag, String}) -> case list_to_term(String) of - {ok, Value}-> + {ok, Value} -> {list_to_atom(Tag), Value}; - Error-> + Error -> throw(Error) end. @@ -111,8 +111,8 @@ transform_entity({Tag, String})-> list_to_term(String) -> {ok, T, _} = erl_scan:string(String++"."), case catch erl_parse:parse_term(T) of - {ok, Term} -> - {ok, Term}; + {ok,Term} -> + {ok,Term}; Error -> - {error, Error, String} + {error,{Error,String}} end. diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 9e597edf38..c24a7c238b 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -24,10 +24,10 @@ -module(ct_framework). --export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, report/2, warn/1]). --export([error_notification/4]). +-export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, get_all_cases/1]). +-export([report/2, warn/1, error_notification/4]). --export([overview_html_header/1]). +-export([get_logopts/0, format_comment/1, get_html_wrapper/3]). -export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]). @@ -36,6 +36,10 @@ -include("ct_event.hrl"). -include("ct_util.hrl"). +-define(val(Key, List), proplists:get_value(Key, List)). +-define(val(Key, List, Def), proplists:get_value(Key, List, Def)). +-define(rev(L), lists:reverse(L)). + %%%----------------------------------------------------------------- %%% @spec init_tc(Mod,Func,Args) -> {ok,NewArgs} | {error,Reason} | %%% {skip,Reason} | {auto_skip,Reason} @@ -48,6 +52,8 @@ %%% @doc Test server framework callback, called by the test_server %%% when a new test case is started. init_tc(Mod,Func,Config) -> + %% in case Mod == ct_framework, lookup the suite name + Suite = get_suite_name(Mod, Config), %% check if previous testcase was interpreted and has left %% a "dead" trace window behind - if so, kill it case ct_util:get_testdata(interpret) of @@ -57,34 +63,36 @@ init_tc(Mod,Func,Config) -> _ -> ok end, - %% check if we need to add defaults explicitly because %% there's no init_per_suite exported from Mod {InitFailed,DoInit} = case ct_util:get_testdata(curr_tc) of - {Mod,{suite0_failed,_}=Failure} -> + {Suite,{suite0_failed,_}=Failure} -> {Failure,false}; - {Mod,_} -> + {?MODULE,_} -> % should not really happen {false,false}; - _ when Func == init_per_suite -> + {Suite,_} -> % Func is not 1st case in suite {false,false}; - _ -> + _ when Func == init_per_suite -> % defaults will be added anyway + {false,false}; + _ -> % first case in suite {false,true} end, case InitFailed of false -> - ct_util:set_testdata({curr_tc,{Mod,Func}}), - case ct_util:read_suite_data({seq,Mod,Func}) of + ct_util:set_testdata({curr_tc,{Suite,Func}}), + case ct_util:read_suite_data({seq,Suite,Func}) of undefined -> init_tc1(Mod,Func,Config,DoInit); Seq when is_atom(Seq) -> - case ct_util:read_suite_data({seq,Mod,Seq}) of + case ct_util:read_suite_data({seq,Suite,Seq}) of [Func|TCs] -> % this is the 1st case in Seq %% make sure no cases in this seq are marked as failed %% from an earlier execution in the same suite - lists:foreach(fun(TC) -> - ct_util:save_suite_data({seq,Mod,TC},Seq) - end, TCs); + lists:foreach( + fun(TC) -> + ct_util:save_suite_data({seq,Suite,TC},Seq) + end, TCs); _ -> ok end, @@ -98,6 +106,17 @@ init_tc(Mod,Func,Config) -> {skip,InitFailed} end. +init_tc1(?MODULE,error_in_suite,[Config0],_) when is_list(Config0) -> + ct_logs:init_tc(false), + ct_event:notify(#event{name=tc_start, + node=node(), + data={?MODULE,error_in_suite}}), + case ?val(error, Config0) of + undefined -> + {skip,"unknown_error_in_suite"}; + Reason -> + {skip,Reason} + end; init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> Config1 = case ct_util:read_suite_data(last_saved_config) of @@ -116,41 +135,46 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> Config = lists:keydelete(watchdog,1,Config1), if Func /= init_per_suite, DoInit /= true -> ok; - true -> + true -> %% delete all default values used in previous suite ct_config:delete_default_config(suite), %% release all name -> key bindings (once per suite) ct_config:release_allocated() end, - TestCaseInfo = - case catch apply(Mod,Func,[]) of - Result when is_list(Result) -> Result; - _ -> [] - end, + + GroupPath = ?val(tc_group_path, Config, []), + AllGroups = [?val(tc_group_properties, Config, []) | GroupPath], + %% clear all config data default values set by previous %% testcase info function (these should only survive the %% testcase, not the whole suite) - ct_config:delete_default_config(testcase), - case add_defaults(Mod,Func,TestCaseInfo,DoInit) of + FuncSpec = group_or_func(Func,Config0), + if is_tuple(FuncSpec) -> % group + ok; + true -> + ct_config:delete_default_config(testcase) + end, + %% in case Mod == ct_framework, lookup the suite name + Suite = get_suite_name(Mod, Config), + case add_defaults(Mod,Func,AllGroups,DoInit) of Error = {suite0_failed,_} -> - ct_logs:init_tc(), - FuncSpec = group_or_func(Func,Config0), + ct_logs:init_tc(false), ct_event:notify(#event{name=tc_start, node=node(), data={Mod,FuncSpec}}), - ct_util:set_testdata({curr_tc,{Mod,Error}}), + ct_util:set_testdata({curr_tc,{Suite,Error}}), {error,Error}; {SuiteInfo,MergeResult} -> case MergeResult of {error,Reason} when DoInit == false -> - ct_logs:init_tc(), - FuncSpec = group_or_func(Func,Config0), + ct_logs:init_tc(false), ct_event:notify(#event{name=tc_start, node=node(), data={Mod,FuncSpec}}), {skip,Reason}; _ -> - init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) + init_tc2(Mod,Func,SuiteInfo,MergeResult, + Config,DoInit) end end; init_tc1(_Mod,_Func,Args,_DoInit) -> @@ -194,20 +218,26 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> Conns -> ct_util:silence_connections(Conns) end, - - ct_logs:init_tc(), + if Func /= init_per_suite, DoInit /= true -> + ct_logs:init_tc(false); + true -> + ct_logs:init_tc(true) + end, FuncSpec = group_or_func(Func,Config), ct_event:notify(#event{name=tc_start, node=node(), data={Mod,FuncSpec}}), - - case configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of + + case catch configure(MergedInfo1,MergedInfo1,SuiteInfo, + {FuncSpec,DoInit},Config) of {suite0_failed,Reason} -> ct_util:set_testdata({curr_tc,{Mod,{suite0_failed,{require,Reason}}}}), {skip,{require_failed_in_suite0,Reason}}; {error,Reason} -> {auto_skip,{require_failed,Reason}}; - {ok, FinalConfig} -> + {'EXIT',Reason} -> + {auto_skip,Reason}; + {ok,FinalConfig} -> case MergeResult of {error,Reason} -> %% suite0 configure finished now, report that @@ -236,82 +266,219 @@ ct_suite_init(Mod, Func, [Config]) when is_list(Config) -> Else end. -add_defaults(Mod,Func,FuncInfo,DoInit) -> - case (catch Mod:suite()) of +add_defaults(Mod,Func, GroupPath, DoInit) -> + Suite = get_suite_name(Mod, GroupPath), + case (catch Suite:suite()) of {'EXIT',{undef,_}} -> - SuiteInfo = merge_with_suite_defaults(Mod,[]), + SuiteInfo = merge_with_suite_defaults(Suite,[]), SuiteInfoNoCTH = [I || I <- SuiteInfo, element(1,I) =/= ct_hooks], - case add_defaults1(Mod,Func,FuncInfo,SuiteInfoNoCTH,DoInit) of + case add_defaults1(Mod,Func, GroupPath, SuiteInfoNoCTH, DoInit) of Error = {error,_} -> {SuiteInfo,Error}; MergedInfo -> {SuiteInfo,MergedInfo} end; - {'EXIT',Reason} -> + {'EXIT',Reason} -> + ErrStr = io_lib:format("~n*** ERROR *** " + "~w:suite/0 failed: ~p~n", + [Suite,Reason]), + io:format(ErrStr, []), + io:format(user, ErrStr, []), {suite0_failed,{exited,Reason}}; SuiteInfo when is_list(SuiteInfo) -> case lists:all(fun(E) when is_tuple(E) -> true; (_) -> false end, SuiteInfo) of true -> - SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfo), + SuiteInfo1 = merge_with_suite_defaults(Suite, SuiteInfo), SuiteInfoNoCTH = [I || I <- SuiteInfo1, element(1,I) =/= ct_hooks], - case add_defaults1(Mod,Func,FuncInfo, - SuiteInfoNoCTH,DoInit) of + case add_defaults1(Mod,Func, GroupPath, + SuiteInfoNoCTH, DoInit) of Error = {error,_} -> {SuiteInfo1,Error}; MergedInfo -> {SuiteInfo1,MergedInfo} end; false -> + ErrStr = io_lib:format("~n*** ERROR *** " + "Invalid return value from " + "~w:suite/0: ~p~n", [Suite,SuiteInfo]), + io:format(ErrStr, []), + io:format(user, ErrStr, []), {suite0_failed,bad_return_value} end; - _ -> + SuiteInfo -> + ErrStr = io_lib:format("~n*** ERROR *** " + "Invalid return value from " + "~w:suite/0: ~p~n", [Suite,SuiteInfo]), + io:format(ErrStr, []), + io:format(user, ErrStr, []), {suite0_failed,bad_return_value} end. -add_defaults1(_Mod,init_per_suite,[],SuiteInfo,_DoInit) -> - SuiteInfo; - -add_defaults1(Mod,Func,FuncInfo,SuiteInfo,DoInit) -> - %% mustn't re-require suite variables in test case info function, - %% can result in weird behaviour (suite values get overwritten) +add_defaults1(Mod,Func, GroupPath, SuiteInfo, DoInit) -> + Suite = get_suite_name(Mod, GroupPath), + %% GroupPathInfo (for subgroup on level X) = + %% [LevelXGroupInfo, LevelX-1GroupInfo, ..., TopLevelGroupInfo] + GroupPathInfo = + lists:map(fun(GroupProps) -> + Name = ?val(name, GroupProps), + case catch Suite:group(Name) of + GrInfo when is_list(GrInfo) -> GrInfo; + _ -> [] + end + end, GroupPath), + Args = if Func == init_per_group; Func == ct_init_per_group; + Func == end_per_group; Func == ct_end_per_group -> + [?val(name, hd(GroupPath))]; + true -> + [] + end, + TestCaseInfo = + case catch apply(Mod,Func,Args) of + TCInfo when is_list(TCInfo) -> TCInfo; + _ -> [] + end, + %% let test case info (also for all config funcs) override group info, + %% and lower level group info override higher level info + TCAndGroupInfo = [TestCaseInfo | remove_info_in_prev(TestCaseInfo, + GroupPathInfo)], + %% find and save require terms found in suite info SuiteReqs = [SDDef || SDDef <- SuiteInfo, ((require == element(1,SDDef)) or (default_config == element(1,SDDef)))], - FuncReqs = - [FIDef || FIDef <- FuncInfo, - require == element(1,FIDef)], - case [element(2,Clash) || Clash <- SuiteReqs, - require == element(1, Clash), - true == lists:keymember(element(2,Clash),2, - FuncReqs)] of + case check_for_clashes(TestCaseInfo, GroupPathInfo, SuiteReqs) of [] -> - add_defaults2(Mod,Func,FuncInfo,SuiteInfo,SuiteReqs,DoInit); + add_defaults2(Mod,Func, TCAndGroupInfo,SuiteInfo,SuiteReqs, DoInit); Clashes -> {error,{config_name_already_in_use,Clashes}} end. -add_defaults2(Mod,init_per_suite,IPSInfo,SuiteInfo,SuiteReqs,false) -> - %% not common practise to use a test case info function for - %% init_per_suite (usually handled by suite/0), but let's support - %% it just in case... - add_defaults2(Mod,init_per_suite,IPSInfo,SuiteInfo,SuiteReqs,true); - -add_defaults2(_Mod,_Func,FuncInfo,SuiteInfo,_,false) -> - %% include require elements from test case info, but not from suite/0 - %% (since we've already required those vars) - FuncInfo ++ - [SFDef || SFDef <- SuiteInfo, - require /= element(1,SFDef), - false == lists:keymember(element(1,SFDef),1,FuncInfo)]; - -add_defaults2(_Mod,_Func,FuncInfo,SuiteInfo,SuiteReqs,true) -> - %% We must include require elements from suite/0 here since - %% there's no init_per_suite call before this first test case. - %% Let other test case info elements override those from suite/0. - FuncInfo ++ SuiteReqs ++ - [SDDef || SDDef <- SuiteInfo, - require /= element(1,SDDef), - false == lists:keymember(element(1,SDDef),1,FuncInfo)]. +get_suite_name(?MODULE, [Cfg|_]) when is_list(Cfg), Cfg /= [] -> + get_suite_name(?MODULE, Cfg); + +get_suite_name(?MODULE, Cfg) when is_list(Cfg), Cfg /= [] -> + case ?val(tc_group_properties, Cfg) of + undefined -> + case ?val(suite, Cfg) of + undefined -> ?MODULE; + Suite -> Suite + end; + GrProps -> + case ?val(suite, GrProps) of + undefined -> ?MODULE; + Suite -> Suite + end + end; +get_suite_name(Mod, _) -> + Mod. + +%% Check that alias names are not already in use +check_for_clashes(TCInfo, GrPathInfo, SuiteInfo) -> + {CurrGrInfo,SearchIn} = case GrPathInfo of + [] -> {[],[SuiteInfo]}; + [Curr|Path] -> {Curr,[SuiteInfo|Path]} + end, + ReqNames = fun(Info) -> [element(2,R) || R <- Info, + size(R) == 3, + require == element(1,R)] + end, + ExistingNames = lists:flatten([ReqNames(L) || L <- SearchIn]), + CurrGrReqNs = ReqNames(CurrGrInfo), + GrClashes = [Name || Name <- CurrGrReqNs, + true == lists:member(Name, ExistingNames)], + AllReqNs = CurrGrReqNs ++ ExistingNames, + TCClashes = [Name || Name <- ReqNames(TCInfo), + true == lists:member(Name, AllReqNs)], + TCClashes ++ GrClashes. + +%% Delete the info terms in Terms from all following info lists +remove_info_in_prev(Terms, [[] | Rest]) -> + [[] | remove_info_in_prev(Terms, Rest)]; +remove_info_in_prev(Terms, [Info | Rest]) -> + UniqueInInfo = [U || U <- Info, + ((timetrap == element(1,U)) and + (not lists:keymember(timetrap,1,Terms))) or + ((require == element(1,U)) and + (not lists:member(U,Terms))) or + ((default_config == element(1,U)) and + (not keysmember([default_config,1, + element(2,U),2], Terms)))], + OtherTermsInInfo = [T || T <- Info, + timetrap /= element(1,T), + require /= element(1,T), + default_config /= element(1,T), + false == lists:keymember(element(1,T),1, + Terms)], + KeptInfo = UniqueInInfo ++ OtherTermsInInfo, + [KeptInfo | remove_info_in_prev(Terms ++ KeptInfo, Rest)]; +remove_info_in_prev(_, []) -> + []. + +keysmember([Key,Pos|Next], List) -> + case [Elem || Elem <- List, Key == element(Pos,Elem)] of + [] -> false; + Found -> keysmember(Next, Found) + end; +keysmember([], _) -> true. + + +add_defaults2(Mod,init_per_suite, IPSInfo, SuiteInfo,SuiteReqs, false) -> + add_defaults2(Mod,init_per_suite, IPSInfo, SuiteInfo,SuiteReqs, true); + +add_defaults2(_Mod,IPG, IPGAndGroupInfo, SuiteInfo,SuiteReqs, DoInit) when + IPG == init_per_group ; IPG == ct_init_per_group -> + %% If DoInit == true, we have to process the suite() list, otherwise + %% it has already been handled (see clause for init_per_suite) + case DoInit of + true -> + %% note: we know for sure this is a top level group + Info = lists:flatten([IPGAndGroupInfo, SuiteReqs]), + Info ++ remove_info_in_prev(Info, [SuiteInfo]); + false -> + SuiteInfo1 = + remove_info_in_prev(lists:flatten([IPGAndGroupInfo, + SuiteReqs]), [SuiteInfo]), + %% don't require terms in prev groups (already processed) + case IPGAndGroupInfo of + [IPGInfo] -> + lists:flatten([IPGInfo,SuiteInfo1]); + [IPGInfo | [CurrGroupInfo | PrevGroupInfo]] -> + PrevGroupInfo1 = delete_require_terms(PrevGroupInfo), + lists:flatten([IPGInfo,CurrGroupInfo,PrevGroupInfo1, + SuiteInfo1]) + end + end; + +add_defaults2(_Mod,_Func, TCAndGroupInfo, SuiteInfo,SuiteReqs, false) -> + %% Include require elements from test case info and current group, + %% but not from previous groups or suite/0 (since we've already required + %% those vars). Let test case info elements override group and suite + %% info elements. + SuiteInfo1 = remove_info_in_prev(lists:flatten([TCAndGroupInfo, + SuiteReqs]), [SuiteInfo]), + %% don't require terms in prev groups (already processed) + case TCAndGroupInfo of + [TCInfo] -> + lists:flatten([TCInfo,SuiteInfo1]); + [TCInfo | [CurrGroupInfo | PrevGroupInfo]] -> + PrevGroupInfo1 = delete_require_terms(PrevGroupInfo), + lists:flatten([TCInfo,CurrGroupInfo,PrevGroupInfo1, + SuiteInfo1]) + end; + +add_defaults2(_Mod,_Func, TCInfo, SuiteInfo,SuiteReqs, true) -> + %% Here we have to process the suite info list also (no call to + %% init_per_suite before this first test case). This TC can't belong + %% to a group, or the clause for (ct_)init_per_group would've caught this. + Info = lists:flatten([TCInfo, SuiteReqs]), + lists:flatten([Info,remove_info_in_prev(Info, [SuiteInfo])]). + +delete_require_terms([Info | Prev]) -> + Info1 = [T || T <- Info, + require /= element(1,T), + default_config /= element(1,T)], + [Info1 | delete_require_terms(Prev)]; +delete_require_terms([]) -> + []. merge_with_suite_defaults(Mod,SuiteInfo) -> case lists:keysearch(suite_defaults,1,Mod:module_info(attributes)) of @@ -335,16 +502,17 @@ timetrap_first([Trap = {timetrap,_} | Rest],Info,Found) -> timetrap_first([Other | Rest],Info,Found) -> timetrap_first(Rest,[Other | Info],Found); timetrap_first([],Info,[]) -> - [{timetrap,{minutes,30}} | lists:reverse(Info)]; + [{timetrap,{minutes,30}} | ?rev(Info)]; timetrap_first([],Info,Found) -> - lists:reverse(Found) ++ lists:reverse(Info). + ?rev(Found) ++ ?rev(Info). configure([{require,Required}|Rest],Info,SuiteInfo,Scope,Config) -> case ct:require(Required) of ok -> configure(Rest,Info,SuiteInfo,Scope,Config); Error = {error,Reason} -> - case required_default('_UNDEF',Required,Info,SuiteInfo,Scope) of + case required_default('_UNDEF',Required,Info, + SuiteInfo,Scope) of ok -> configure(Rest,Info,SuiteInfo,Scope,Config); _ -> @@ -386,18 +554,24 @@ configure([],_,_,_,Config) -> {ok,[Config]}. %% the require element in Info may come from suite/0 and -%% should be scoped 'suite', or come from the testcase info -%% function and should then be scoped 'testcase' -required_default(Name,Key,Info,SuiteInfo,{Func,true}) -> +%% should be scoped 'suite', or come from the group info +%% function and be scoped 'group', or come from the testcase +%% info function and then be scoped 'testcase' + +required_default(Name,Key,Info,SuiteInfo,{FuncSpec,true}) -> case try_set_default(Name,Key,SuiteInfo,suite) of ok -> ok; _ -> - required_default(Name,Key,Info,[],{Func,false}) + required_default(Name,Key,Info,[],{FuncSpec,false}) end; required_default(Name,Key,Info,_,{init_per_suite,_}) -> try_set_default(Name,Key,Info,suite); -required_default(Name,Key,Info,_,_) -> +required_default(Name,Key,Info,_,{{init_per_group,GrName,_},_}) -> + try_set_default(Name,Key,Info,{group,GrName}); +required_default(Name,Key,Info,_,{{ct_init_per_group,GrName,_},_}) -> + try_set_default(Name,Key,Info,{group,GrName}); +required_default(Name,Key,Info,_,_FuncSpec) -> try_set_default(Name,Key,Info,testcase). try_set_default(Name,Key,Info,Where) -> @@ -437,7 +611,7 @@ try_set_default(Name,Key,Info,Where) -> %%% @doc Test server framework callback, called by the test_server %%% when a test case is finished. end_tc(Mod, Fun, Args) -> - %% Have to keep end_tc/3 for backwards compatabilty issues + %% Have to keep end_tc/3 for backwards compatibility issues end_tc(Mod, Fun, Args, '$end_tc_dummy'). end_tc(?MODULE,error_in_suite,_, _) -> % bad start! ok; @@ -451,7 +625,6 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> {value,{watchdog,Dog}} -> test_server:timetrap_cancel(Dog); false -> ok end, - %% save the testcase process pid so that it can be used %% to look up the attached trace window later case ct_util:get_testdata(interpret) of @@ -461,12 +634,15 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> _ -> ok end, - ct_util:delete_testdata(comment), ct_util:delete_suite_data(last_saved_config), FuncSpec = case group_or_func(Func,Args) of - {_,GroupName,_Props} = Group -> + {_,GroupName,_Props} = Group -> + if Func == end_per_group; Func == ct_end_per_group -> + ct_config:delete_default_config({group,GroupName}); + true -> ok + end, case lists:keysearch(save_config,1,Args) of {value,{save_config,SaveConfig}} -> ct_util:save_suite_data( @@ -685,12 +861,14 @@ mark_as_failed1(_,_,_,[]) -> ok. group_or_func(Func, Config) when Func == init_per_group; - Func == end_per_group -> - case proplists:get_value(tc_group_properties,Config) of + Func == end_per_group; + Func == ct_init_per_group; + Func == ct_end_per_group -> + case ?val(tc_group_properties, Config) of undefined -> {Func,unknown,[]}; GrProps -> - GrName = proplists:get_value(name,GrProps), + GrName = ?val(name,GrProps), {Func,GrName,proplists:delete(name,GrProps)} end; group_or_func(Func, _Config) -> @@ -714,7 +892,7 @@ get_suite(Mod, all) -> %% (and only) test case so we can report Error properly [{?MODULE,error_in_suite,[[Error]]}]; ConfTests -> - get_all(Mod, ConfTests) + get_all(Mod, ConfTests) end; _ -> E = "Bad return value from "++atom_to_list(Mod)++":groups/0", @@ -728,7 +906,7 @@ get_suite(Mod, all) -> %% group get_suite(Mod, Group={conf,Props,_Init,TCs,_End}) -> - Name = proplists:get_value(name, Props), + Name = ?val(name, Props), case catch apply(Mod, groups, []) of {'EXIT',_} -> [Group]; @@ -746,14 +924,25 @@ get_suite(Mod, Group={conf,Props,_Init,TCs,_End}) -> %% a *subgroup* specified *only* as skipped (and not %% as an explicit test) should not be returned, or %% init/end functions for top groups will be executed - case catch proplists:get_value(name, element(2, hd(ConfTests))) of + case catch ?val(name, element(2, hd(ConfTests))) of Name -> % top group delete_subs(ConfTests, ConfTests); _ -> [] end; false -> - delete_subs(ConfTests, ConfTests) + ConfTests1 = delete_subs(ConfTests, ConfTests), + case ?val(override, Props) of + undefined -> + ConfTests1; + [] -> + ConfTests1; + ORSpec -> + ORSpec1 = if is_tuple(ORSpec) -> [ORSpec]; + true -> ORSpec end, + search_and_override(ConfTests1, + ORSpec1, Mod) + end end end; _ -> @@ -767,6 +956,36 @@ get_suite(Mod, Name) -> %%%----------------------------------------------------------------- +get_all_cases(Suite) -> + case get_suite(Suite, all) of + [{?MODULE,error_in_suite,[[{error,_}=Error]]}] -> + Error; + [{?MODULE,error_in_suite,[[Error]]}] -> + {error,Error}; + Tests -> + Cases = get_all_cases1(Suite, Tests), + ?rev(lists:foldl(fun(TC, TCs) -> + case lists:member(TC, TCs) of + true -> TCs; + false -> [TC | TCs] + end + end, [], Cases)) + end. + +get_all_cases1(Suite, [{conf,_Props,_Init,GrTests,_End} | Tests]) -> + get_all_cases1(Suite, GrTests) ++ get_all_cases1(Suite, Tests); + +get_all_cases1(Suite, [Test | Tests]) when is_atom(Test) -> + [{Suite,Test} | get_all_cases1(Suite, Tests)]; + +get_all_cases1(Suite, [Test | Tests]) -> + [Test | get_all_cases1(Suite, Tests)]; + +get_all_cases1(_, []) -> + []. + +%%%----------------------------------------------------------------- + find_groups(Mod, Name, TCs, GroupDefs) -> Found = find(Mod, Name, TCs, GroupDefs, [], GroupDefs, false), trim(Found). @@ -869,14 +1088,14 @@ delete_subs([], All) -> All. delete_conf({conf,Props,_,_,_}, Confs) -> - Name = proplists:get_value(name, Props), + Name = ?val(name, Props), [Conf || Conf = {conf,Props0,_,_,_} <- Confs, - Name =/= proplists:get_value(name, Props0)]. + Name =/= ?val(name, Props0)]. is_sub({conf,Props,_,_,_}=Conf, [{conf,_,_,Tests,_} | Confs]) -> - Name = proplists:get_value(name, Props), + Name = ?val(name, Props), case lists:any(fun({conf,Props0,_,_,_}) -> - case proplists:get_value(name, Props0) of + case ?val(name, Props0) of N when N == Name -> true; _ -> @@ -978,15 +1197,20 @@ make_conf(Mod, Name, Props, TestSpec) -> _ -> ok end, - {InitConf,EndConf} = + {InitConf,EndConf,ExtraProps} = case erlang:function_exported(Mod,init_per_group,2) of true -> - {{Mod,init_per_group},{Mod,end_per_group}}; + {{Mod,init_per_group},{Mod,end_per_group},[]}; false -> + ct_logs:log("TEST INFO", "init_per_group/2 and " + "end_per_group/2 missing for group " + "~p in ~p, using default.", + [Name,Mod]), {{?MODULE,ct_init_per_group}, - {?MODULE,ct_end_per_group}} + {?MODULE,ct_end_per_group}, + [{suite,Mod}]} end, - {conf,[{name,Name}|Props],InitConf,TestSpec,EndConf}. + {conf,[{name,Name}|Props++ExtraProps],InitConf,TestSpec,EndConf}. %%%----------------------------------------------------------------- @@ -1024,29 +1248,116 @@ expand_groups([H | T], ConfTests, Mod) -> expand_groups([], _ConfTests, _Mod) -> []; expand_groups({group,Name}, ConfTests, Mod) -> - FindConf = - fun({conf,Props,_,_,_}) -> - case proplists:get_value(name, Props) of - Name -> true; - _ -> false + expand_groups({group,Name,default,[]}, ConfTests, Mod); +expand_groups({group,Name,default}, ConfTests, Mod) -> + expand_groups({group,Name,default,[]}, ConfTests, Mod); +expand_groups({group,Name,ORProps}, ConfTests, Mod) when is_list(ORProps) -> + expand_groups({group,Name,ORProps,[]}, ConfTests, Mod); +expand_groups({group,Name,ORProps,SubORSpec}, ConfTests, Mod) -> + FindConf = + fun(Conf = {conf,Props,Init,Ts,End}) -> + case ?val(name, Props) of + Name when ORProps == default -> + [Conf]; + Name -> + [{conf,[{name,Name}|ORProps],Init,Ts,End}]; + _ -> + [] end end, - case lists:filter(FindConf, ConfTests) of - [ConfTest|_] -> - expand_groups(ConfTest, ConfTests, Mod); + case lists:flatmap(FindConf, ConfTests) of [] -> - E = "Invalid reference to group "++ - atom_to_list(Name)++" in "++ - atom_to_list(Mod)++":all/0", - throw({error,list_to_atom(E)}) + throw({error,invalid_ref_msg(Name, Mod)}); + Matching when SubORSpec == [] -> + Matching; + Matching -> + override_props(Matching, SubORSpec, Name,Mod) end; expand_groups(SeqOrTC, _ConfTests, _Mod) -> SeqOrTC. +%% search deep for the matching conf test and modify it and any +%% sub tests according to the override specification +search_and_override([Conf = {conf,Props,Init,Tests,End}], ORSpec, Mod) -> + Name = ?val(name, Props), + case lists:keysearch(Name, 1, ORSpec) of + {value,{Name,default}} -> + [Conf]; + {value,{Name,ORProps}} -> + [{conf,[{name,Name}|ORProps],Init,Tests,End}]; + {value,{Name,default,[]}} -> + [Conf]; + {value,{Name,default,SubORSpec}} -> + override_props([Conf], SubORSpec, Name,Mod); + {value,{Name,ORProps,SubORSpec}} -> + override_props([{conf,[{name,Name}|ORProps], + Init,Tests,End}], SubORSpec, Name,Mod); + _ -> + [{conf,Props,Init,search_and_override(Tests,ORSpec,Mod),End}] + end. + +%% Modify the Tests element according to the override specification +override_props([{conf,Props,Init,Tests,End} | Confs], SubORSpec, Name,Mod) -> + {Subs,SubORSpec1} = override_sub_props(Tests, [], SubORSpec, Mod), + [{conf,Props,Init,Subs,End} | override_props(Confs, SubORSpec1, Name,Mod)]; +override_props([], [], _,_) -> + []; +override_props([], SubORSpec, Name,Mod) -> + Es = [invalid_ref_msg(Name, element(1,Spec), Mod) || Spec <- SubORSpec], + throw({error,Es}). + +override_sub_props([], New, ORSpec, _) -> + {?rev(New),ORSpec}; +override_sub_props([T = {conf,Props,Init,Tests,End} | Ts], + New, ORSpec, Mod) -> + Name = ?val(name, Props), + case lists:keysearch(Name, 1, ORSpec) of + {value,Spec} -> % group found in spec + Props1 = + case element(2, Spec) of + default -> Props; + ORProps -> [{name,Name} | ORProps] + end, + case catch element(3, Spec) of + Undef when Undef == [] ; 'EXIT' == element(1, Undef) -> + override_sub_props(Ts, [{conf,Props1,Init,Tests,End} | New], + lists:keydelete(Name, 1, ORSpec), Mod); + SubORSpec when is_list(SubORSpec) -> + case override_sub_props(Tests, [], SubORSpec, Mod) of + {Subs,[]} -> + override_sub_props(Ts, [{conf,Props1,Init, + Subs,End} | New], + lists:keydelete(Name, 1, ORSpec), + Mod); + {_,NonEmptySpec} -> + Es = [invalid_ref_msg(Name, element(1, GrRef), + Mod) || GrRef <- NonEmptySpec], + throw({error,Es}) + end; + BadGrSpec -> + throw({error,{invalid_form,BadGrSpec}}) + end; + _ -> % not a group in spec + override_sub_props(Ts, [T | New], ORSpec, Mod) + end; +override_sub_props([TC | Ts], New, ORSpec, Mod) -> + override_sub_props(Ts, [TC | New], ORSpec, Mod). + +invalid_ref_msg(Name, Mod) -> + E = "Invalid reference to group "++ + atom_to_list(Name)++" in "++ + atom_to_list(Mod)++":all/0", + list_to_atom(E). + +invalid_ref_msg(Name0, Name1, Mod) -> + E = "Invalid reference to group "++ + atom_to_list(Name1)++" from "++atom_to_list(Name0)++ + " in "++atom_to_list(Mod)++":all/0", + list_to_atom(E). %%!============================================================ %%! The support for sequences by means of using sequences/0 -%%! will be removed in OTP R14. The code below is only kept +%%! will be removed in OTP R15. The code below is only kept %%! for backwards compatibility. From OTP R13 groups with %%! sequence property should be used instead! %%!============================================================ @@ -1159,13 +1470,15 @@ error_in_suite(Config) -> %% if the group config functions are missing in the suite, %% use these instead ct_init_per_group(GroupName, Config) -> - ct_logs:log("WARNING", "init_per_group/2 for ~w missing " + ct:comment(io_lib:format("start of ~p", [GroupName])), + ct_logs:log("TEST INFO", "init_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), Config. ct_end_per_group(GroupName, _) -> - ct_logs:log("WARNING", "end_per_group/2 for ~w missing " + ct:comment(io_lib:format("end of ~p", [GroupName])), + ct_logs:log("TEST INFO", "end_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), ok. @@ -1178,8 +1491,8 @@ report(What,Data) -> loginfo -> %% logfiles and direcories have been created for a test and the %% top level test index page needs to be refreshed - TestName = filename:basename(proplists:get_value(topdir, Data), ".logs"), - RunDir = proplists:get_value(rundir, Data), + TestName = filename:basename(?val(topdir, Data), ".logs"), + RunDir = ?val(rundir, Data), ct_logs:make_all_suites_index({TestName,RunDir}), ok; tests_start -> @@ -1218,6 +1531,10 @@ report(What,Data) -> tests_done -> ok; tc_start -> + %% Data = {{Suite,Func},LogFileName} + ct_event:sync_notify(#event{name=tc_logfile, + node=node(), + data=Data}), ok; tc_done -> {_Suite,Case,Result} = Data, @@ -1242,12 +1559,20 @@ report(What,Data) -> ok; {end_per_group,_} -> ok; + {ct_init_per_group,_} -> + ok; + {ct_end_per_group,_} -> + ok; {_,ok} -> add_to_stats(ok); {_,{skipped,{failed,{_,init_per_testcase,_}}}} -> add_to_stats(auto_skipped); {_,{skipped,{require_failed,_}}} -> add_to_stats(auto_skipped); + {_,{skipped,{timetrap_error,_}}} -> + add_to_stats(auto_skipped); + {_,{skipped,{invalid_time_format,_}}} -> + add_to_stats(auto_skipped); {_,{skipped,_}} -> add_to_stats(user_skipped); {_,{SkipOrFail,_Reason}} -> @@ -1273,11 +1598,24 @@ report(What,Data) -> node=node(), data=Data}), ct_hooks:on_tc_skip(What, Data), - if Case /= end_per_suite, Case /= end_per_group -> + if Case /= end_per_suite, + Case /= end_per_group, + Case /= ct_end_per_group -> add_to_stats(auto_skipped); true -> ok end; + framework_error -> + case Data of + {{M,F},E} -> + ct_event:sync_notify(#event{name=tc_done, + node=node(), + data={M,F,{framework_error,E}}}); + _ -> + ct_event:sync_notify(#event{name=tc_done, + node=node(), + data=Data}) + end; _ -> ok end, @@ -1332,30 +1670,21 @@ add_data_dir(File,Config) when is_list(File) -> end. %%%----------------------------------------------------------------- -%%% @spec overview_html_header(TestName) -> Header -overview_html_header(TestName) -> - TestName1 = lists:flatten(io_lib:format("~p", [TestName])), - Label = case application:get_env(common_test, test_label) of - {ok,Lbl} when Lbl =/= undefined -> - "<H1><FONT color=\"green\">" ++ Lbl ++ "</FONT></H1>\n"; - _ -> - "" - end, - Bgr = case ct_logs:basic_html() of - true -> - ""; - false -> - CTPath = code:lib_dir(common_test), - TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), - " background=\"" ++ TileFile ++ "\"" - end, - - ["<html>\n", - "<head><title>Test ", TestName1, " results</title>\n", - "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", - "</head>\n", - "<body", Bgr, " bgcolor=\"white\" text=\"black\" ", - "link=\"blue\" vlink=\"purple\" alink=\"red\">\n", - Label, - "<H2>Results from test ", TestName1, "</H2>\n"]. +%%% @spec get_logopts() -> [LogOpt] +get_logopts() -> + case ct_util:get_testdata(logopts) of + undefined -> + []; + LogOpts -> + LogOpts + end. +%%%----------------------------------------------------------------- +%%% @spec format_comment(Comment) -> HtmlComment +format_comment(Comment) -> + "<font color=\"green\">" ++ Comment ++ "</font>". + +%%%----------------------------------------------------------------- +%%% @spec get_html_wrapper(TestName, PrintLabel, Cwd) -> Header +get_html_wrapper(TestName, PrintLabel, Cwd) -> + ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd). diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl index f243b87f54..c42adbbdd9 100644 --- a/lib/common_test/src/ct_hooks.erl +++ b/lib/common_test/src/ct_hooks.erl @@ -34,6 +34,12 @@ %% If you change this, remember to update ct_util:look -> stop clause as well. -define(config_name, ct_hooks). +%% All of the hooks which are to be started by default. Remove by issuing +%% -enable_builtin_hooks false to when starting common test. +-define(BUILTIN_HOOKS,[#ct_hook_config{ module = cth_log_redirect, + opts = [], + prio = ctfirst }]). + -record(ct_hook_config, {id, module, prio, scope, opts = [], state = []}). %% ------------------------------------------------------------------------- @@ -44,7 +50,8 @@ -spec init(State :: term()) -> ok | {error, Reason :: term()}. init(Opts) -> - call(get_new_hooks(Opts, undefined), ok, init, []). + call(get_new_hooks(Opts, undefined) ++ get_builtin_hooks(Opts), + ok, init, []). %% @doc Called after all suites are done. @@ -171,8 +178,9 @@ call_generic(#ct_hook_config{ module = Mod, state = State} = Hook, call(Fun, Config, Meta) -> maybe_lock(), Hooks = get_hooks(), - Res = call(get_new_hooks(Config, Fun) ++ - [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks], + Calls = get_new_hooks(Config, Fun) ++ + [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks], + Res = call(resort(Calls,Hooks,Meta), remove(?config_name,Config), Meta, Hooks), maybe_unlock(), Res. @@ -198,7 +206,7 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) -> {Hooks ++ [NewHook], [{NewId, call_init}, {NewId,NextFun} | Rest]} end, - call(resort(NewRest,NewHooks), Config, Meta, NewHooks) + call(resort(NewRest,NewHooks,Meta), Config, Meta, NewHooks) catch Error:Reason -> Trace = erlang:get_stacktrace(), ct_logs:log("Suite Hook","Failed to start a CTH: ~p:~p", @@ -214,7 +222,7 @@ call([{HookId, Fun} | Rest], Config, Meta, Hooks) -> {NewConf, NewHook} = Fun(Hook, Config, Meta), NewCalls = get_new_hooks(NewConf, Fun), NewHooks = lists:keyreplace(HookId, #ct_hook_config.id, Hooks, NewHook), - call(resort(NewCalls ++ Rest,NewHooks), %% Resort if call_init changed prio + call(resort(NewCalls ++ Rest,NewHooks,Meta), %% Resort if call_init changed prio remove(?config_name, NewConf), Meta, terminate_if_scope_ends(HookId, Meta, NewHooks)) catch throw:{error_in_cth_call,Reason} -> @@ -283,6 +291,14 @@ get_new_hooks(Config) when is_list(Config) -> get_new_hooks(_Config) -> []. +get_builtin_hooks(Opts) -> + case proplists:get_value(enable_builtin_hooks,Opts) of + false -> + []; + _Else -> + [{HookConf, call_id, undefined} || HookConf <- ?BUILTIN_HOOKS] + end. + save_suite_data_async(Hooks) -> ct_util:save_suite_data_async(?config_name, Hooks). @@ -290,9 +306,21 @@ get_hooks() -> lists:keysort(#ct_hook_config.prio,ct_util:read_suite_data(?config_name)). %% Sort all calls in this order: -%% call_id < call_init < Hook Priority 1 < .. < Hook Priority N +%% call_id < call_init < ctfirst < Priority 1 < .. < Priority N < ctlast %% If Hook Priority is equal, check when it has been installed and %% sort on that instead. +%% If we are doing a cleanup call i.e. {post,pre}_end_per_*, all priorities +%% are reversed. Probably want to make this sorting algorithm pluginable +%% as some point... +resort(Calls,Hooks,[F|_R]) when F == post_end_per_testcase; + F == pre_end_per_group; + F == post_end_per_group; + F == pre_end_per_suite; + F == post_end_per_suite -> + lists:reverse(resort(Calls,Hooks)); +resort(Calls,Hooks,_Meta) -> + resort(Calls,Hooks). + resort(Calls, Hooks) -> lists:sort( fun({_,_,_},_) -> @@ -311,6 +339,14 @@ resort(Calls, Hooks) -> %% If priorities are equal, we check the position in the %% hooks list pos(Id1,Hooks) < pos(Id2,Hooks); + P1 == ctfirst -> + true; + P2 == ctfirst -> + false; + P1 == ctlast -> + false; + P2 == ctlast -> + true; true -> P1 < P2 end @@ -331,7 +367,7 @@ catch_apply(M,F,A, Default) -> catch error:Reason -> case erlang:get_stacktrace() of %% Return the default if it was the CTH module which did not have the function. - [{M,F,A}|_] when Reason == undef -> + [{M,F,A,_}|_] when Reason == undef -> Default; Trace -> ct_logs:log("Suite Hook","Call to CTH failed: ~p:~p", diff --git a/lib/common_test/src/ct_line.erl b/lib/common_test/src/ct_line.erl deleted file mode 100644 index 4af9da5463..0000000000 --- a/lib/common_test/src/ct_line.erl +++ /dev/null @@ -1,266 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2003-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% -%% - -%%% @doc Parse transform for inserting line numbers - --module(ct_line). - --record(vars, {module, % atom() Module name - vsn, % atom() - - init_info=[], % [{M,F,A,C,L}] - - function, % atom() - arity, % int() - clause, % int() - lines, % [int()] - depth, % int() - is_guard=false % boolean - }). - --export([parse_transform/2, - line/1]). - -line(LOC={{Mod,Func},_Line}) -> - Lines = case get(test_server_loc) of - [{{Mod,Func},_}|Ls] -> - Ls; - Ls when is_list(Ls) -> - case length(Ls) of - 10 -> - [_|T]=lists:reverse(Ls), - lists:reverse(T); - _ -> - Ls - end; - _ -> - [] - end, - put(test_server_loc,[LOC|Lines]). - -parse_transform(Forms, _Options) -> - transform(Forms, _Options). - -%% forms(Fs) -> lists:map(fun (F) -> form(F) end, Fs). - -transform(Forms, _Options)-> - Vars0 = #vars{}, - {ok, MungedForms, _Vars} = transform(Forms, [], Vars0), - MungedForms. - - -transform([Form|Forms], MungedForms, Vars) -> - case munge(Form, Vars) of - ignore -> - transform(Forms, MungedForms, Vars); - {MungedForm, Vars2} -> - transform(Forms, [MungedForm|MungedForms], Vars2) - end; -transform([], MungedForms, Vars) -> - {ok, lists:reverse(MungedForms), Vars}. - -%% This code traverses the abstract code, stored as the abstract_code -%% chunk in the BEAM file, as described in absform(3) for Erlang/OTP R8B -%% (Vsn=abstract_v2). -%% The abstract format after preprocessing differs slightly from the abstract -%% format given eg using epp:parse_form, this has been noted in comments. -munge(Form={attribute,_,module,Module}, Vars) -> - Vars2 = Vars#vars{module=Module}, - {Form, Vars2}; - -munge({function,0,module_info,_Arity,_Clauses}, _Vars) -> - ignore; % module_info will be added again when the forms are recompiled -munge({function,Line,Function,Arity,Clauses}, Vars) -> - Vars2 = Vars#vars{function=Function, - arity=Arity, - clause=1, - lines=[], - depth=1}, - {MungedClauses, Vars3} = munge_clauses(Clauses, Vars2, []), - {{function,Line,Function,Arity,MungedClauses}, Vars3}; -munge(Form, Vars) -> % attributes - {Form, Vars}. - -munge_clauses([{clause,Line,Pattern,Guards,Body}|Clauses], Vars, MClauses) -> - {MungedGuards, _Vars} = munge_exprs(Guards, Vars#vars{is_guard=true},[]), - - case Vars#vars.depth of - 1 -> % function clause - {MungedBody, Vars2} = munge_body(Body, Vars#vars{depth=2}, []), - ClauseInfo = {Vars2#vars.module, - Vars2#vars.function, - Vars2#vars.arity, - Vars2#vars.clause, - length(Vars2#vars.lines)}, - InitInfo = [ClauseInfo | Vars2#vars.init_info], - Vars3 = Vars2#vars{init_info=InitInfo, - clause=(Vars2#vars.clause)+1, - lines=[], - depth=1}, - munge_clauses(Clauses, Vars3, - [{clause,Line,Pattern,MungedGuards,MungedBody}| - MClauses]); - - 2 -> % receive-, case- or if clause - {MungedBody, Vars2} = munge_body(Body, Vars, []), - munge_clauses(Clauses, Vars2, - [{clause,Line,Pattern,MungedGuards,MungedBody}| - MClauses]) - end; -munge_clauses([], Vars, MungedClauses) -> - {lists:reverse(MungedClauses), Vars}. - -munge_body([Expr|Body], Vars, MungedBody) -> - %% Here is the place to add a call to cover:bump/6! - Line = element(2, Expr), - Lines = Vars#vars.lines, - case lists:member(Line,Lines) of - true -> % already a bump at this line! - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - munge_body(Body, Vars2, [MungedExpr|MungedBody]); - false -> - Bump = {call, 0, {remote,0,{atom,0,?MODULE},{atom,0,line}}, - [{tuple,0,[{tuple,0,[{atom,0,Vars#vars.module}, - {atom, 0, Vars#vars.function}]}, - {integer, 0, Line}]}]}, - Lines2 = [Line|Lines], - - {MungedExpr, Vars2} = munge_expr(Expr, Vars#vars{lines=Lines2}), - munge_body(Body, Vars2, [MungedExpr,Bump|MungedBody]) - end; -munge_body([], Vars, MungedBody) -> - {lists:reverse(MungedBody), Vars}. - -munge_expr({match,Line,ExprL,ExprR}, Vars) -> - {MungedExprL, Vars2} = munge_expr(ExprL, Vars), - {MungedExprR, Vars3} = munge_expr(ExprR, Vars2), - {{match,Line,MungedExprL,MungedExprR}, Vars3}; -munge_expr({tuple,Line,Exprs}, Vars) -> - {MungedExprs, Vars2} = munge_exprs(Exprs, Vars, []), - {{tuple,Line,MungedExprs}, Vars2}; -munge_expr({record,Line,Expr,Exprs}, Vars) -> - %% Only for Vsn=raw_abstract_v1 - {MungedExprName, Vars2} = munge_expr(Expr, Vars), - {MungedExprFields, Vars3} = munge_exprs(Exprs, Vars2, []), - {{record,Line,MungedExprName,MungedExprFields}, Vars3}; -munge_expr({record_field,Line,ExprL,ExprR}, Vars) -> - %% Only for Vsn=raw_abstract_v1 - {MungedExprL, Vars2} = munge_expr(ExprL, Vars), - {MungedExprR, Vars3} = munge_expr(ExprR, Vars2), - {{record_field,Line,MungedExprL,MungedExprR}, Vars3}; -munge_expr({cons,Line,ExprH,ExprT}, Vars) -> - {MungedExprH, Vars2} = munge_expr(ExprH, Vars), - {MungedExprT, Vars3} = munge_expr(ExprT, Vars2), - {{cons,Line,MungedExprH,MungedExprT}, Vars3}; -munge_expr({op,Line,Op,ExprL,ExprR}, Vars) -> - {MungedExprL, Vars2} = munge_expr(ExprL, Vars), - {MungedExprR, Vars3} = munge_expr(ExprR, Vars2), - {{op,Line,Op,MungedExprL,MungedExprR}, Vars3}; -munge_expr({op,Line,Op,Expr}, Vars) -> - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - {{op,Line,Op,MungedExpr}, Vars2}; -munge_expr({'catch',Line,Expr}, Vars) -> - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - {{'catch',Line,MungedExpr}, Vars2}; -munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs}, - Vars) when Vars#vars.is_guard==false-> - {MungedExprM, Vars2} = munge_expr(ExprM, Vars), - {MungedExprF, Vars3} = munge_expr(ExprF, Vars2), - {MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []), - {{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4}; -munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs}, - Vars) when Vars#vars.is_guard==true -> - %% Difference in abstract format after preprocessing: BIF calls in guards - %% are translated to {remote,...} (which is not allowed as source form) - %% NOT NECESSARY FOR Vsn=raw_abstract_v1 - munge_expr({call,Line1,ExprF,Exprs}, Vars); -munge_expr({call,Line,Expr,Exprs}, Vars) -> - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - {MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []), - {{call,Line,MungedExpr,MungedExprs}, Vars3}; -munge_expr({lc,Line,Expr,LC}, Vars) -> - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - {MungedLC, Vars3} = munge_lc(LC, Vars2, []), - {{lc,Line,MungedExpr,MungedLC}, Vars3}; -munge_expr({block,Line,Body}, Vars) -> - {MungedBody, Vars2} = munge_body(Body, Vars, []), - {{block,Line,MungedBody}, Vars2}; -munge_expr({'if',Line,Clauses}, Vars) -> - {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []), - {{'if',Line,MungedClauses}, Vars2}; -munge_expr({'case',Line,Expr,Clauses}, Vars) -> - {MungedExpr,Vars2} = munge_expr(Expr,Vars), - {MungedClauses,Vars3} = munge_clauses(Clauses, Vars2, []), - {{'case',Line,MungedExpr,MungedClauses}, Vars3}; -munge_expr({'receive',Line,Clauses}, Vars) -> - {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []), - {{'receive',Line,MungedClauses}, Vars2}; -munge_expr({'receive',Line,Clauses,Expr,Body}, Vars) -> - {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []), - {MungedExpr, Vars3} = munge_expr(Expr, Vars2), - {MungedBody, Vars4} = munge_body(Body, Vars3, []), - {{'receive',Line,MungedClauses,MungedExpr,MungedBody}, Vars4}; -munge_expr({'try',Line,Exprs,Clauses,CatchClauses}, Vars) -> - {MungedExprs, Vars1} = munge_exprs(Exprs, Vars, []), - {MungedClauses, Vars2} = munge_clauses(Clauses, Vars1, []), - {MungedCatchClauses, Vars3} = munge_clauses(CatchClauses, Vars2, []), - {{'try',Line,MungedExprs,MungedClauses,MungedCatchClauses}, Vars3}; -%% Difference in abstract format after preprocessing: Funs get an extra -%% element Extra. -%% NOT NECESSARY FOR Vsn=raw_abstract_v1 -munge_expr({'fun',Line,{function,Name,Arity},_Extra}, Vars) -> - {{'fun',Line,{function,Name,Arity}}, Vars}; -munge_expr({'fun',Line,{clauses,Clauses},_Extra}, Vars) -> - {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []), - {{'fun',Line,{clauses,MungedClauses}}, Vars2}; -munge_expr({'fun',Line,{clauses,Clauses}}, Vars) -> - %% Only for Vsn=raw_abstract_v1 - {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []), - {{'fun',Line,{clauses,MungedClauses}}, Vars2}; -munge_expr(Form, Vars) -> % var|char|integer|float|string|atom|nil|bin|eof - {Form, Vars}. - -munge_exprs([Expr|Exprs], Vars, MungedExprs) when Vars#vars.is_guard==true, - is_list(Expr) -> - {MungedExpr, _Vars} = munge_exprs(Expr, Vars, []), - munge_exprs(Exprs, Vars, [MungedExpr|MungedExprs]); -munge_exprs([Expr|Exprs], Vars, MungedExprs) -> - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - munge_exprs(Exprs, Vars2, [MungedExpr|MungedExprs]); -munge_exprs([], Vars, MungedExprs) -> - {lists:reverse(MungedExprs), Vars}. - -munge_lc([{generate,Line,Pattern,Expr}|LC], Vars, MungedLC) -> - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - munge_lc(LC, Vars2, [{generate,Line,Pattern,MungedExpr}|MungedLC]); -munge_lc([Expr|LC], Vars, MungedLC) -> - {MungedExpr, Vars2} = munge_expr(Expr, Vars), - munge_lc(LC, Vars2, [MungedExpr|MungedLC]); -munge_lc([], Vars, MungedLC) -> - {lists:reverse(MungedLC), Vars}. - - - - - - - - - - diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index b839521e24..19ad7b26d8 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -28,15 +28,17 @@ -module(ct_logs). --export([init/1,close/1,init_tc/0,end_tc/1]). --export([get_log_dir/0,log/3,start_log/1,cont_log/2,end_log/0]). +-export([init/1,close/2,init_tc/1,end_tc/1]). +-export([get_log_dir/0,get_log_dir/1]). +-export([log/3,start_log/1,cont_log/2,end_log/0]). -export([set_stylesheet/2,clear_stylesheet/1]). -export([add_external_logs/1,add_link/3]). -export([make_last_run_index/0]). -export([make_all_suites_index/1,make_all_runs_index/1]). +-export([get_ts_html_wrapper/3]). %% Logging stuff directly from testcase --export([tc_log/3,tc_print/3,tc_pal/3, +-export([tc_log/3,tc_print/3,tc_pal/3,ct_log/3, basic_html/0]). %% Simulate logger process for use without ct environment running @@ -53,6 +55,7 @@ -define(all_runs_name, "all_runs.html"). -define(index_name, "index.html"). -define(totals_name, "totals.info"). +-define(css_default, "ct_default.css"). -define(table_color1,"#ADD8E6"). -define(table_color2,"#E4F0FE"). @@ -97,11 +100,11 @@ logdir_node_prefix() -> logdir_prefix()++"."++atom_to_list(node()). %%%----------------------------------------------------------------- -%%% @spec close(Info) -> ok +%%% @spec close(Info, StartDir) -> ok %%% %%% @doc Create index pages with test results and close the CT Log %%% (tool-internal use only). -close(Info) -> +close(Info, StartDir) -> make_last_run_index(), ct_event:notify(#event{name=stop_logging,node=node(),data=[]}), @@ -124,14 +127,29 @@ close(Info) -> ok; Error -> io:format("Warning! Cleanup failed: ~p~n", [Error]) - end; + end, + make_all_suites_index(stop), + make_all_runs_index(stop); true -> - file:set_cwd("..") - end, - - make_all_suites_index(stop), - make_all_runs_index(stop), - + file:set_cwd(".."), + make_all_suites_index(stop), + make_all_runs_index(stop), + case ct_util:get_profile_data(browser, StartDir) of + undefined -> + ok; + BrowserData -> + case {proplists:get_value(prog, BrowserData), + proplists:get_value(args, BrowserData), + proplists:get_value(page, BrowserData)} of + {Prog,Args,Page} when is_list(Args), + is_list(Page) -> + URL = "\"file://" ++ ?abs(Page) ++ "\"", + ct_util:open_url(Prog, Args, URL); + _ -> + ok + end + end + end, ok. %%%----------------------------------------------------------------- @@ -147,7 +165,12 @@ clear_stylesheet(TC) -> %%%----------------------------------------------------------------- %%% @spec get_log_dir() -> {ok,Dir} | {error,Reason} get_log_dir() -> - call(get_log_dir). + call({get_log_dir,false}). + +%%%----------------------------------------------------------------- +%%% @spec get_log_dir(ReturnAbsName) -> {ok,Dir} | {error,Reason} +get_log_dir(ReturnAbsName) -> + call({get_log_dir,ReturnAbsName}). %%%----------------------------------------------------------------- %%% make_last_run_index() -> ok @@ -182,15 +205,15 @@ cast(Msg) -> ?MODULE ! Msg end. - %%%----------------------------------------------------------------- -%%% @spec init_tc() -> ok +%%% @spec init_tc(RefreshLog) -> ok %%% %%% @doc Test case initiation (tool-internal use only). %%% %%% <p>This function is called by ct_framework:init_tc/3</p> -init_tc() -> - call({init_tc,self(),group_leader()}), +init_tc(RefreshLog) -> + call({init_tc,self(),group_leader(),RefreshLog}), + io:format(xhtml("", "<br />")), ok. %%%----------------------------------------------------------------- @@ -360,6 +383,23 @@ tc_pal(Category,Format,Args) -> ok. +%%%----------------------------------------------------------------- +%%% @spec tc_pal(Category,Format,Args) -> ok +%%% Category = atom() +%%% Format = string() +%%% Args = list() +%%% +%%% @doc Print and log to the ct framework log +%%% +%%% <p>This function is called by internal ct functions to +%%% force logging to the ct framework log</p> +ct_log(Category,Format,Args) -> + cast({ct_log,[{div_header(Category),[]}, + {Format,Args}, + {div_footer(),[]}]}), + ok. + + %%%================================================================= %%% Internal functions int_header() -> @@ -417,7 +457,6 @@ logger(Parent,Mode) -> timer:sleep(1000), Time1 = calendar:local_time(), Dir1 = make_dirname(Time1), - {Time1,Dir1}; false -> {Time0,Dir0} @@ -425,8 +464,44 @@ logger(Parent,Mode) -> %%! <--- file:make_dir(Dir), + AbsDir = ?abs(Dir), + put(ct_run_dir, AbsDir), + + case basic_html() of + true -> + put(basic_html, true); + BasicHtml -> + put(basic_html, BasicHtml), + %% copy stylesheet to log dir (both top dir and test run + %% dir) so logs are independent of Common Test installation + {ok,Cwd} = file:get_cwd(), + CTPath = code:lib_dir(common_test), + CSSFileSrc = filename:join(filename:join(CTPath, "priv"), + ?css_default), + CSSFileDestTop = filename:join(Cwd, ?css_default), + CSSFileDestRun = filename:join(AbsDir, ?css_default), + case file:copy(CSSFileSrc, CSSFileDestTop) of + {error,Reason0} -> + io:format(user, "ERROR! "++ + "CSS file ~p could not be copied to ~p. "++ + "Reason: ~p~n", + [CSSFileSrc,CSSFileDestTop,Reason0]), + exit({css_file_error,CSSFileDestTop}); + _ -> + case file:copy(CSSFileSrc, CSSFileDestRun) of + {error,Reason1} -> + io:format(user, "ERROR! "++ + "CSS file ~p could not be copied to ~p. "++ + "Reason: ~p~n", + [CSSFileSrc,CSSFileDestRun,Reason1]), + exit({css_file_error,CSSFileDestRun}); + _ -> + ok + end + end + end, ct_event:notify(#event{name=start_logging,node=node(), - data=?abs(Dir)}), + data=AbsDir}), make_all_runs_index(start), make_all_suites_index(start), case Mode of @@ -441,7 +516,7 @@ logger(Parent,Mode) -> Parent ! {started,self(),{Time,filename:absname("")}}, set_evmgr_gl(CtLogFd), logger_loop(#logger_state{parent=Parent, - log_dir=Dir, + log_dir=AbsDir, start_time=Time, orig_GL=group_leader(), ct_log_fd=CtLogFd, @@ -469,8 +544,8 @@ logger_loop(State) -> [Str,Args]), %% stop the testcase, we need %% to see the fault - exit(Pid,logging_failed), - ok; + exit(Pid,{log_printout_error,Str,Args}), + []; IoStr when IoList == [] -> [IoStr]; IoStr -> @@ -490,22 +565,30 @@ logger_loop(State) -> [begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List], logger_loop(State#logger_state{tc_groupleaders=TCGLs}) end; - {{init_tc,TCPid,GL},From} -> + {{init_tc,TCPid,GL,RefreshLog},From} -> print_style(GL, State#logger_state.stylesheet), set_evmgr_gl(GL), TCGLs = add_tc_gl(TCPid,GL,State), + if not RefreshLog -> + ok; + true -> + make_last_run_index(State#logger_state.start_time) + end, return(From,ok), logger_loop(State#logger_state{tc_groupleaders=TCGLs}); {{end_tc,TCPid},From} -> set_evmgr_gl(State#logger_state.ct_log_fd), return(From,ok), logger_loop(State#logger_state{tc_groupleaders=rm_tc_gl(TCPid,State)}); - {get_log_dir,From} -> + {{get_log_dir,true},From} -> return(From,{ok,State#logger_state.log_dir}), logger_loop(State); + {{get_log_dir,false},From} -> + return(From,{ok,filename:basename(State#logger_state.log_dir)}), + logger_loop(State); {make_last_run_index,From} -> make_last_run_index(State#logger_state.start_time), - return(From,State#logger_state.log_dir), + return(From,filename:basename(State#logger_state.log_dir)), logger_loop(State); {set_stylesheet,_,SSFile} when State#logger_state.stylesheet == SSFile -> logger_loop(State); @@ -516,7 +599,12 @@ logger_loop(State) -> {clear_stylesheet,_} when State#logger_state.stylesheet == undefined -> logger_loop(State); {clear_stylesheet,_} -> - logger_loop(State#logger_state{stylesheet=undefined}); + logger_loop(State#logger_state{stylesheet=undefined}); + {ct_log, List} -> + Fd = State#logger_state.ct_log_fd, + [begin io:format(Fd,Str,Args),io:nl(Fd) end || + {Str,Args} <- List], + logger_loop(State); stop -> io:format(State#logger_state.ct_log_fd, int_header()++int_footer(), @@ -616,7 +704,7 @@ set_evmgr_gl(GL) -> open_ctlog() -> {ok,Fd} = file:open(?ct_log_name,[write]), - io:format(Fd,header("Common Test Framework"),[]), + io:format(Fd, header("Common Test Framework Log"), []), case file:consult(ct_run:variables_file_name("../")) of {ok,Vars} -> io:format(Fd, config_table(Vars), []); @@ -631,17 +719,22 @@ open_ctlog() -> end, print_style(Fd,undefined), io:format(Fd, - "<br><br><h2>Progress Log</h2>\n" - "<pre>\n",[]), + xhtml("<br><br><h2>Progress Log</h2>\n<pre>\n", + "<br /><br /><h4>PROGRESS LOG</h4>\n<pre>\n"), []), Fd. print_style(Fd,undefined) -> - io:format(Fd, - "<style>\n" - "div.ct_internal { background:lightgrey; color:black }\n" - "div.default { background:lightgreen; color:black }\n" - "</style>\n", - []); + case basic_html() of + true -> + io:format(Fd, + "<style>\n" + "div.ct_internal { background:lightgrey; color:black; }\n" + "div.default { background:lightgreen; color:black; }\n" + "</style>\n", + []); + _ -> + ok + end; print_style(Fd,StyleSheet) -> case file:read_file(StyleSheet) of @@ -651,20 +744,19 @@ print_style(Fd,StyleSheet) -> 0 -> string:str(Str,"<STYLE>"); N0 -> N0 end, - case Pos0 of - 0 -> print_style_error(Fd,StyleSheet,missing_style_tag); - _ -> - Pos1 = case string:str(Str,"</style>") of - 0 -> string:str(Str,"</STYLE>"); - N1 -> N1 - end, - case Pos1 of - 0 -> - print_style_error(Fd,StyleSheet,missing_style_end_tag); - _ -> - Style = string:sub_string(Str,Pos0,Pos1+7), - io:format(Fd,"~s\n",[Style]) - end + Pos1 = case string:str(Str,"</style>") of + 0 -> string:str(Str,"</STYLE>"); + N1 -> N1 + end, + if (Pos0 == 0) and (Pos1 /= 0) -> + print_style_error(Fd,StyleSheet,missing_style_start_tag); + (Pos0 /= 0) and (Pos1 == 0) -> + print_style_error(Fd,StyleSheet,missing_style_end_tag); + Pos0 /= 0 -> + Style = string:sub_string(Str,Pos0,Pos1+7), + io:format(Fd,"~s\n",[Style]); + Pos0 == 0 -> + io:format(Fd,"<style>~s</style>\n",[Str]) end; {error,Reason} -> print_style_error(Fd,StyleSheet,Reason) @@ -682,7 +774,7 @@ print_style_error(Fd,StyleSheet,Reason) -> print_style(Fd,undefined). close_ctlog(Fd) -> - io:format(Fd,"</pre>",[]), + io:format(Fd,"\n</pre>\n",[]), io:format(Fd,footer(),[]), file:close(Fd). @@ -813,12 +905,13 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, CrashDumpName = SuiteName ++ "_erl_crash.dump", case filelib:is_file(CrashDumpName) of true -> - [" <A HREF=\"", CrashDumpName, - "\">(CrashDump)</A>"]; + [" <a href=\"", CrashDumpName, + "\">(CrashDump)</a>"]; false -> "" end end, + CtRunDir = filename:dirname(filename:dirname(Link)), {Lbl,Timestamp,Node,AllInfo} = case All of {true,OldRuns} -> @@ -827,33 +920,41 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, 0 -> "-"; _ -> NodeOrDate end, - N = ["<TD ALIGN=right><FONT SIZE=-1>",Node1,"</FONT></TD>\n"], - CtRunDir = filename:dirname(filename:dirname(Link)), - L = ["<TD ALIGN=center><FONT SIZE=-1><B>",Label,"</FONT></B></TD>\n"], - T = ["<TD><FONT SIZE=-1>",timestamp(CtRunDir),"</FONT></TD>\n"], + TS = timestamp(CtRunDir), + N = xhtml(["<td align=right><font size=\"-1\">",Node1, + "</font></td>\n"], + ["<td align=right>",Node1,"</td>\n"]), + L = xhtml(["<td align=center><font size=\"-1\"><b>",Label, + "</font></b></td>\n"], + ["<td align=center><b>",Label,"</b></td>\n"]), + T = xhtml(["<td><font size=\"-1\">",TS,"</font></td>\n"], + ["<td>",TS,"</td>\n"]), CtLogFile = filename:join(CtRunDir,?ct_log_name), OldRunsLink = case OldRuns of [] -> "none"; - _ -> "<A HREF=\""++?all_runs_name++"\">Old Runs</A>" + _ -> "<a href=\""++?all_runs_name++"\">Old Runs</a>" end, - A=["<TD><FONT SIZE=-1><A HREF=\"",CtLogFile,"\">CT Log</A></FONT></TD>\n", - "<TD><FONT SIZE=-1>",OldRunsLink,"</FONT></TD>\n"], + A = xhtml(["<td><font size=\"-1\"><a href=\"",CtLogFile, + "\">CT Log</a></font></td>\n", + "<td><font size=\"-1\">",OldRunsLink,"</font></td>\n"], + ["<td><a href=\"",CtLogFile,"\">CT Log</a></td>\n", + "<td>",OldRunsLink,"</td>\n"]), {L,T,N,A}; false -> {"","","",""} end, NotBuiltStr = if NotBuilt == 0 -> - ["<TD ALIGN=right>",integer_to_list(NotBuilt),"</TD>\n"]; + ["<td align=right>",integer_to_list(NotBuilt),"</td>\n"]; true -> - ["<TD ALIGN=right><A HREF=\"",?ct_log_name,"\">", - integer_to_list(NotBuilt),"</A></TD>\n"] + ["<td align=right><a href=\"",filename:join(CtRunDir,?ct_log_name),"\">", + integer_to_list(NotBuilt),"</a></td>\n"] end, FailStr = if Fail > 0 -> - ["<FONT color=\"red\">", - integer_to_list(Fail),"</FONT>"]; + ["<font color=\"red\">", + integer_to_list(Fail),"</font>"]; true -> integer_to_list(Fail) end, @@ -861,31 +962,33 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, if AutoSkip == undefined -> {UserSkip,"?","?"}; true -> ASStr = if AutoSkip > 0 -> - ["<FONT color=\"brown\">", - integer_to_list(AutoSkip),"</FONT>"]; + ["<font color=\"brown\">", + integer_to_list(AutoSkip),"</font>"]; true -> integer_to_list(AutoSkip) end, {UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr} end, - ["<TR valign=top>\n", - "<TD><FONT SIZE=-1><A HREF=\"",LogFile,"\">",SuiteName,"</A>",CrashDumpLink,"</FONT></TD>\n", - Lbl, - Timestamp, - "<TD ALIGN=right>",integer_to_list(Success),"</TD>\n", - "<TD ALIGN=right>",FailStr,"</TD>\n", - "<TD ALIGN=right>",integer_to_list(AllSkip), - " (",UserSkipStr,"/",AutoSkipStr,")</TD>\n", - NotBuiltStr, - Node, - AllInfo, - "</TR>\n"]. + [xhtml("<tr valign=top>\n", + ["<tr class=\"",odd_or_even(),"\">\n"]), + xhtml("<td><font size=\"-1\"><a href=\"", "<td><a href=\""), + LogFile,"\">",SuiteName,"</a>", CrashDumpLink, + xhtml("</font></td>\n", "</td>\n"), + Lbl, Timestamp, + "<td align=right>",integer_to_list(Success),"</td>\n", + "<td align=right>",FailStr,"</td>\n", + "<td align=right>",integer_to_list(AllSkip), + " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", + NotBuiltStr, Node, AllInfo, "</tr>\n"]. + total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) -> {Label,TimestampCell,AllInfo} = case All of true -> - {"<TD> </TD>\n", - "<TD> </TD>\n", - "<TD> </TD>\n<TD> </TD>\n"}; + {"<td> </td>\n", + "<td> </td>\n", + "<td> </td>\n" + "<td> </td>\n" + "<td> </td>\n"}; false -> {"","",""} end, @@ -895,17 +998,15 @@ total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) -> true -> {UserSkip+AutoSkip, integer_to_list(UserSkip),integer_to_list(AutoSkip)} end, - ["<TR valign=top>\n", - "<TD><B>Total</B></TD>", - Label, - TimestampCell, - "<TD ALIGN=right><B>",integer_to_list(Success),"<B></TD>\n", - "<TD ALIGN=right><B>",integer_to_list(Fail),"<B></TD>\n", - "<TD ALIGN=right>",integer_to_list(AllSkip), - " (",UserSkipStr,"/",AutoSkipStr,")</TD>\n", - "<TD ALIGN=right><B>",integer_to_list(NotBuilt),"<B></TD>\n", - AllInfo, - "</TR>\n"]. + [xhtml("<tr valign=top>\n", + ["<tr class=\"",odd_or_even(),"\">\n"]), + "<td><b>Total</b></td>\n", Label, TimestampCell, + "<td align=right><b>",integer_to_list(Success),"<b></td>\n", + "<td align=right><b>",integer_to_list(Fail),"<b></td>\n", + "<td align=right>",integer_to_list(AllSkip), + " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", + "<td align=right><b>",integer_to_list(NotBuilt),"<b></td>\n", + AllInfo, "</tr>\n"]. not_built(_BaseName,_LogDir,_All,[]) -> 0; @@ -964,41 +1065,52 @@ index_header(Label, StartTime) -> undefined -> header("Test Results", format_time(StartTime)); _ -> - header("Test Results for \"" ++ Label ++ "\"", + header("Test Results for '" ++ Label ++ "'", format_time(StartTime)) end, [Head | - ["<CENTER>\n", - "<P><A HREF=\"",?ct_log_name,"\">Common Test Framework Log</A></P>", - "<TABLE border=\"3\" cellpadding=\"5\" " - "BGCOLOR=\"",?table_color3,"\">\n" - "<th><B>Test Name</B></th>\n", - "<th><font color=\"",?table_color3,"\">_</font>Ok" - "<font color=\"",?table_color3,"\">_</font></th>\n" + ["<center>\n", + xhtml(["<p><a href=\"",?ct_log_name, + "\">Common Test Framework Log</a></p>"], + ["<br />" + "<div id=\"button_holder\" class=\"btn\">\n" + "<a href=\"",?ct_log_name, + "\">COMMON TEST FRAMEWORK LOG</a>\n</div>"]), + xhtml("<br>\n", "<br /><br /><br />\n"), + xhtml(["<table border=\"3\" cellpadding=\"5\" " + "bgcolor=\"",?table_color3,"\">\n"], "<table>\n"), + "<th><b>Test Name</b></th>\n", + xhtml(["<th><font color=\"",?table_color3,"\">_</font>Ok" + "<font color=\"",?table_color3,"\">_</font></th>\n"], + "<th>Ok</th>\n"), "<th>Failed</th>\n", - "<th>Skipped<br>(User/Auto)</th>\n" - "<th>Missing<br>Suites</th>\n" + "<th>Skipped", xhtml("<br>", "<br />"), "(User/Auto)</th>\n" + "<th>Missing", xhtml("<br>", "<br />"), "Suites</th>\n" "\n"]]. - all_suites_index_header() -> {ok,Cwd} = file:get_cwd(), all_suites_index_header(Cwd). all_suites_index_header(IndexDir) -> LogDir = filename:basename(IndexDir), - AllRuns = "All test runs in \"" ++ LogDir ++ "\"", + AllRuns = xhtml(["All test runs in \"" ++ LogDir ++ "\""], + "ALL RUNS"), + AllRunsLink = xhtml(["<a href=\"",?all_runs_name,"\">",AllRuns,"</a>\n"], + ["<div id=\"button_holder\" class=\"btn\">\n" + "<a href=\"",?all_runs_name,"\">",AllRuns,"</a>\n</div>"]), [header("Test Results") | - ["<CENTER>\n", - "<A HREF=\"",?all_runs_name,"\">",AllRuns,"</A>\n", - "<br><br>\n", - "<TABLE border=\"3\" cellpadding=\"5\" " - "BGCOLOR=\"",?table_color2,"\">\n" + ["<center>\n", + AllRunsLink, + xhtml("<br><br>\n", "<br /><br />\n"), + xhtml(["<table border=\"3\" cellpadding=\"5\" " + "bgcolor=\"",?table_color2,"\">\n"], "<table>\n"), "<th>Test Name</th>\n", "<th>Label</th>\n", "<th>Test Run Started</th>\n", - "<th><font color=\"",?table_color2,"\">_</font>Ok" - "<font color=\"",?table_color2,"\">_</font></th>\n" + xhtml(["<th><font color=\"",?table_color2,"\">_</font>Ok" + "<font color=\"",?table_color2,"\">_</font></th>\n"], + "<th>Ok</th>\n"), "<th>Failed</th>\n", "<th>Skipped<br>(User/Auto)</th>\n" "<th>Missing<br>Suites</th>\n" @@ -1011,17 +1123,25 @@ all_runs_header() -> {ok,Cwd} = file:get_cwd(), LogDir = filename:basename(Cwd), Title = "All test runs in \"" ++ LogDir ++ "\"", + IxLink = [xhtml(["<p><a href=\"",?index_name, + "\">Test Index Page</a></p>"], + ["<div id=\"button_holder\" class=\"btn\">\n" + "<a href=\"",?index_name, + "\">TEST INDEX PAGE</a>\n</div>"]), + xhtml("<br>\n", "<br /><br />\n")], [header(Title) | - ["<CENTER><TABLE border=\"3\" cellpadding=\"5\" " - "BGCOLOR=\"",?table_color1,"\">\n" - "<th><B>History</B></th>\n" - "<th><B>Node</B></th>\n" - "<th><B>Label</B></th>\n" + ["<center>\n", IxLink, + xhtml(["<table border=\"3\" cellpadding=\"5\" " + "bgcolor=\"",?table_color1,"\">\n"], "<table>\n"), + "<th><b>History</b></th>\n" + "<th><b>Node</b></th>\n" + "<th><b>Label</b></th>\n" "<th>Tests</th>\n" - "<th><B>Test Names</B></th>\n" - "<th>Total</th>\n" - "<th><font color=\"",?table_color1,"\">_</font>Ok" - "<font color=\"",?table_color1,"\">_</font></th>\n" + "<th><b>Test Names</b></th>\n" + "<th>Total</th>\n", + xhtml(["<th><font color=\"",?table_color1,"\">_</font>Ok" + "<font color=\"",?table_color1,"\">_</font></th>\n"], + "<th>Ok</th>\n"), "<th>Failed</th>\n" "<th>Skipped<br>(User/Auto)</th>\n" "<th>Missing<br>Suites</th>\n" @@ -1034,60 +1154,56 @@ header(Title, SubTitle) -> header1(Title, SubTitle) -> SubTitleHTML = if SubTitle =/= "" -> - ["<CENTER>\n", - "<H2>" ++ SubTitle ++ "</H2>\n", - "</CENTER>\n<BR>\n"]; - true -> "<BR>\n" + ["<center>\n", + "<h3>" ++ SubTitle ++ "</h3>\n", + xhtml("</center>\n<br>\n", "</center>\n<br />\n")]; + true -> xhtml("<br>\n", "<br />\n") end, - ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n" - "<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n" - "<HTML>\n", - "<HEAD>\n", - - "<TITLE>" ++ Title ++ " " ++ SubTitle ++ "</TITLE>\n", - "<META HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE\">\n", - - "</HEAD>\n", - - body_tag(), - - "<!-- ---- DOCUMENT TITLE ---- -->\n", - - "<CENTER>\n", - "<H1>" ++ Title ++ "</H1>\n", - "</CENTER>\n", - SubTitleHTML, - - "<!-- ---- CONTENT ---- -->\n"]. + CSSFile = xhtml(fun() -> "" end, + fun() -> make_relative(locate_default_css_file()) end), + [xhtml(["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", + "<html>\n"], + ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n", + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n", + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"]), + "<!-- autogenerated by '"++atom_to_list(?MODULE)++"' -->\n", + "<head>\n", + "<title>" ++ Title ++ " " ++ SubTitle ++ "</title>\n", + "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", + xhtml("", + ["<link rel=\"stylesheet\" href=\"",CSSFile,"\" type=\"text/css\">"]), + "</head>\n", + body_tag(), + "<center>\n", + "<h1>" ++ Title ++ "</h1>\n", + "</center>\n", + SubTitleHTML,"\n"]. index_footer() -> - ["</TABLE>\n" - "</CENTER>\n" | footer()]. + ["</table>\n" + "</center>\n" | footer()]. footer() -> - ["<P><CENTER>\n" - "<BR><BR>\n" - "<HR>\n" - "<P><FONT SIZE=-1>\n" + ["<center>\n", + xhtml("<br><br>\n<hr>\n", "<br /><br />\n"), + xhtml("<p><font size=\"-1\">\n", "<div class=\"copyright\">"), "Copyright © ", year(), - " <A HREF=\"http://erlang.ericsson.se\">Open Telecom Platform</A><BR>\n" - "Updated: <!date>", current_time(), "<!/date><BR>\n" - "</FONT>\n" - "</CENTER>\n" + " <a href=\"http://www.erlang.org\">Open Telecom Platform</a>", + xhtml("<br>\n", "<br />\n"), + "Updated: <!date>", current_time(), "<!/date>", + xhtml("<br>\n", "<br />\n"), + xhtml("</font></p>\n", "</div>\n"), + "</center>\n" "</body>\n"]. body_tag() -> - case basic_html() of - true -> - "<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" " - "vlink=\"#800080\" alink=\"#FF0000\">\n"; - false -> - CTPath = code:lib_dir(common_test), - TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), - "<body background=\"" ++ TileFile ++ "\" bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" " - "vlink=\"#800080\" alink=\"#FF0000\">\n" - end. + CTPath = code:lib_dir(common_test), + TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), + xhtml("<body background=\"" ++ TileFile ++ + "\" bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" " + "vlink=\"#800080\" alink=\"#FF0000\">\n", + "<body>\n"). current_time() -> format_time(calendar:local_time()). @@ -1217,20 +1333,25 @@ config_table(Vars) -> [config_table_header()|config_table1(Vars)]. config_table_header() -> - ["<h2>Configuration</h2>\n", - "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color1, - "\"\n", + [ + xhtml(["<h2>Configuration</h2>\n" + "<table border=\"3\" cellpadding=\"5\" bgcolor=\"",?table_color1,"\"\n"], + "<h4>CONFIGURATION</h4>\n<table>\n"), "<tr><th>Key</th><th>Value</th></tr>\n"]. config_table1([{Key,Value}|Vars]) -> - ["<tr><td>", atom_to_list(Key), "</td>\n", - "<td><pre>",io_lib:format("~p",[Value]),"</pre></td></tr>\n" | + [xhtml(["<tr><td>", atom_to_list(Key), "</td>\n", + "<td><pre>",io_lib:format("~p",[Value]),"</pre></td></tr>\n"], + ["<tr class=\"", odd_or_even(), "\">\n", + "<td>", atom_to_list(Key), "</td>\n", + "<td>", io_lib:format("~p",[Value]), "</td>\n</tr>\n"]) | config_table1(Vars)]; config_table1([]) -> ["</table>\n"]. make_all_runs_index(When) -> + put(basic_html, basic_html()), AbsName = ?abs(?all_runs_name), notify_and_lock_file(AbsName), if When == start -> ok; @@ -1239,8 +1360,7 @@ make_all_runs_index(When) -> Dirs = filelib:wildcard(logdir_prefix()++"*.*"), DirsSorted = (catch sort_all_runs(Dirs)), Header = all_runs_header(), - BasicHtml = basic_html(), - Index = [runentry(Dir, BasicHtml) || Dir <- DirsSorted], + Index = [runentry(Dir) || Dir <- DirsSorted], Result = file:write_file(AbsName,Header++Index++index_footer()), if When == start -> ok; true -> io:put_chars("done\n") @@ -1268,22 +1388,22 @@ sort_all_runs(Dirs) -> interactive_link() -> [Dir|_] = lists:reverse(filelib:wildcard(logdir_prefix()++"*.*")), CtLog = filename:join(Dir,"ctlog.html"), - Body = ["Log from last interactive run: <A HREF=\"",CtLog,"\">", - timestamp(Dir),"</A>"], + Body = ["Log from last interactive run: <a href=\"",CtLog,"\">", + timestamp(Dir),"</a>"], file:write_file("last_interactive.html",Body), io:format("~n~nUpdated ~s\n" "Any CT activities will be logged here\n", [?abs("last_interactive.html")]). -runentry(Dir, BasicHtml) -> +runentry(Dir) -> TotalsFile = filename:join(Dir,?totals_name), TotalsStr = case read_totals_file(TotalsFile) of {Node,Label,Logs,{TotSucc,TotFail,UserSkip,AutoSkip,NotBuilt}} -> TotFailStr = if TotFail > 0 -> - ["<FONT color=\"red\">", - integer_to_list(TotFail),"</FONT>"]; + ["<font color=\"red\">", + integer_to_list(TotFail),"</font>"]; true -> integer_to_list(TotFail) end, @@ -1291,8 +1411,8 @@ runentry(Dir, BasicHtml) -> if AutoSkip == undefined -> {UserSkip,"?","?"}; true -> ASStr = if AutoSkip > 0 -> - ["<FONT color=\"brown\">", - integer_to_list(AutoSkip),"</FONT>"]; + ["<font color=\"brown\">", + integer_to_list(AutoSkip),"</font>"]; true -> integer_to_list(AutoSkip) end, {UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr} @@ -1324,30 +1444,49 @@ runentry(Dir, BasicHtml) -> lists:flatten(io_lib:format("~s...",[Trunc])) end, Total = TotSucc+TotFail+AllSkip, - A = ["<TD ALIGN=center><FONT SIZE=-1>",Node,"</FONT></TD>\n", - "<TD ALIGN=center><FONT SIZE=-1><B>",Label,"</B></FONT></TD>\n", - "<TD ALIGN=right>",NoOfTests,"</TD>\n"], - B = if BasicHtml -> - ["<TD ALIGN=center><FONT SIZE=-1>",TestNamesTrunc,"</FONT></TD>\n"]; - true -> - ["<TD ALIGN=center TITLE='",TestNames,"'><FONT SIZE=-1> ", - TestNamesTrunc,"</FONT></TD>\n"] - end, - C = ["<TD ALIGN=right>",integer_to_list(Total),"</TD>\n", - "<TD ALIGN=right>",integer_to_list(TotSucc),"</TD>\n", - "<TD ALIGN=right>",TotFailStr,"</TD>\n", - "<TD ALIGN=right>",integer_to_list(AllSkip), - " (",UserSkipStr,"/",AutoSkipStr,")</TD>\n", - "<TD ALIGN=right>",integer_to_list(NotBuilt),"</TD>\n"], + A = xhtml(["<td align=center><font size=\"-1\">",Node, + "</font></td>\n", + "<td align=center><font size=\"-1\"><b>",Label, + "</b></font></td>\n", + "<td align=right>",NoOfTests,"</td>\n"], + ["<td align=center>",Node,"</td>\n", + "<td align=center><b>",Label,"</b></td>\n", + "<td align=right>",NoOfTests,"</td>\n"]), + B = xhtml(["<td align=center title='",TestNames,"'><font size=\"-1\"> ", + TestNamesTrunc,"</font></td>\n"], + ["<td align=center title='",TestNames,"'> ", + TestNamesTrunc,"</td>\n"]), + C = ["<td align=right>",integer_to_list(Total),"</td>\n", + "<td align=right>",integer_to_list(TotSucc),"</td>\n", + "<td align=right>",TotFailStr,"</td>\n", + "<td align=right>",integer_to_list(AllSkip), + " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", + "<td align=right>",integer_to_list(NotBuilt),"</td>\n"], A++B++C; _ -> - ["<TD ALIGN=center><FONT size=-1 color=\"red\">", - "Test data missing or corrupt","</FONT></TD>\n"] + A = xhtml(["<td align=center><font size=\"-1\" color=\"red\">" + "Test data missing or corrupt</font></td>\n", + "<td align=center><font size=\"-1\">?</font></td>\n", + "<td align=right>?</td>\n"], + ["<td align=center><font color=\"red\">" + "Test data missing or corrupt</font></td>\n", + "<td align=center>?</td>\n", + "<td align=right>?</td>\n"]), + B = xhtml(["<td align=center><font size=\"-1\">?</font></td>\n"], + ["<td align=center>?</td>\n"]), + C = ["<td align=right>?</td>\n", + "<td align=right>?</td>\n", + "<td align=right>?</td>\n", + "<td align=right>?</td>\n", + "<td align=right>?</td>\n"], + A++B++C end, Index = filename:join(Dir,?index_name), - ["<TR>\n" - "<TD><FONT SIZE=-1><A HREF=\"",Index,"\">",timestamp(Dir),"</A>",TotalsStr,"</FONT></TD>\n" - "</TR>\n"]. + [xhtml("<tr>\n", ["<tr class=\"",odd_or_even(),"\">\n"]), + xhtml(["<td><font size=\"-1\"><a href=\"",Index,"\">",timestamp(Dir),"</a>", + TotalsStr,"</font></td>\n"], + ["<td><a href=\"",Index,"\">",timestamp(Dir),"</a>",TotalsStr,"</td>\n"]), + "</tr>\n"]. write_totals_file(Name,Label,Logs,Totals) -> AbsName = ?abs(Name), @@ -1441,6 +1580,7 @@ timestamp(Dir) -> %% Creates the top level index file. When == start | refresh. %% A copy of the dir tree under logdir is cached as a result. make_all_suites_index(When) when is_atom(When) -> + put(basic_html, basic_html()), AbsIndexName = ?abs(?index_name), notify_and_lock_file(AbsIndexName), LogDirs = filelib:wildcard(logdir_prefix()++".*/*"++?logdir_ext), @@ -1452,6 +1592,7 @@ make_all_suites_index(When) when is_atom(When) -> %% This updates the top level index file using cached data from %% the initial index file creation. make_all_suites_index(NewTestData = {_TestName,DirName}) -> + put(basic_html, basic_html()), %% AllLogDirs = [{TestName,Label,Missing,{LastLogDir,Summary},OldDirs}|...] {AbsIndexName,LogDirData} = ct_util:get_testdata(test_index), @@ -1809,6 +1950,38 @@ last_test([], Latest) -> Latest. %%%----------------------------------------------------------------- +%%% @spec xhtml(HTML, XHTML) -> HTML | XHTML +%%% +%%% @doc +%%% +xhtml(HTML, XHTML) when is_function(HTML), + is_function(XHTML) -> + case get(basic_html) of + true -> HTML(); + _ -> XHTML() + end; +xhtml(HTML, XHTML) -> + case get(basic_html) of + true -> HTML; + _ -> XHTML + end. + +%%%----------------------------------------------------------------- +%%% @spec odd_or_even() -> "odd" | "even" +%%% +%%% @doc +%%% +odd_or_even() -> + case get(odd_or_even) of + even -> + put(odd_or_even, odd), + "even"; + _ -> + put(odd_or_even, even), + "odd" + end. + +%%%----------------------------------------------------------------- %%% @spec basic_html() -> true | false %%% %%% @doc @@ -1820,3 +1993,149 @@ basic_html() -> _ -> false end. + +%%%----------------------------------------------------------------- +%%% @spec locate_default_css_file() -> CSSFile +%%% +%%% @doc +%%% +locate_default_css_file() -> + {ok,CWD} = file:get_cwd(), + CSSFileInCwd = filename:join(CWD, ?css_default), + case filelib:is_file(CSSFileInCwd) of + true -> + CSSFileInCwd; + false -> + CSSResultFile = + case {whereis(?MODULE),self()} of + {Self,Self} -> + %% executed on the ct_logs process + filename:join(get(ct_run_dir), ?css_default); + _ -> + %% executed on other process than ct_logs + {ok,RunDir} = get_log_dir(true), + filename:join(RunDir, ?css_default) + end, + case filelib:is_file(CSSResultFile) of + true -> + CSSResultFile; + false -> + %% last resort, try use css file in CT installation + CTPath = code:lib_dir(common_test), + filename:join(filename:join(CTPath, "priv"), ?css_default) + end + end. + +%%%----------------------------------------------------------------- +%%% @spec make_relative(AbsDir, Cwd) -> RelDir +%%% +%%% @doc Return directory path to File (last element of AbsDir), which +%%% is the path relative to Cwd. Examples when Cwd == "/ldisk/test/logs": +%%% make_relative("/ldisk/test/logs/run/trace.log") -> "run/trace.log" +%%% make_relative("/ldisk/test/trace.log") -> "../trace.log" +%%% make_relative("/ldisk/test/logs/trace.log") -> "trace.log" +make_relative(AbsDir) -> + {ok,Cwd} = file:get_cwd(), + make_relative(AbsDir, Cwd). + +make_relative(AbsDir, Cwd) -> + DirTokens = filename:split(AbsDir), + CwdTokens = filename:split(Cwd), + filename:join(make_relative1(DirTokens, CwdTokens)). + +make_relative1([T | DirTs], [T | CwdTs]) -> + make_relative1(DirTs, CwdTs); +make_relative1(Last = [_File], []) -> + Last; +make_relative1(Last = [_File], CwdTs) -> + Ups = ["../" || _ <- CwdTs], + Ups ++ Last; +make_relative1(DirTs, []) -> + DirTs; +make_relative1(DirTs, CwdTs) -> + Ups = ["../" || _ <- CwdTs], + Ups ++ DirTs. + +%%%----------------------------------------------------------------- +%%% @spec get_ts_html_wrapper(TestName, PrintLabel, Cwd) -> {Mode,Header,Footer} +%%% +%%% @doc +%%% +get_ts_html_wrapper(TestName, PrintLabel, Cwd) -> + TestName1 = if is_list(TestName) -> + lists:flatten(TestName); + true -> + lists:flatten(io_lib:format("~p", [TestName])) + end, + Basic = basic_html(), + LabelStr = + if not PrintLabel -> + ""; + true -> + case {Basic,application:get_env(common_test, test_label)} of + {true,{ok,Lbl}} when Lbl =/= undefined -> + "<h1><font color=\"green\">" ++ Lbl ++ "</font></h1>\n"; + {_,{ok,Lbl}} when Lbl =/= undefined -> + "<div class=\"label\">'" ++ Lbl ++ "'</div>\n"; + _ -> + "" + end + end, + CTPath = code:lib_dir(common_test), + {ok,CtLogdir} = get_log_dir(true), + AllRuns = make_relative(filename:join(filename:dirname(CtLogdir), + ?all_runs_name), Cwd), + TestIndex = make_relative(filename:join(filename:dirname(CtLogdir), + ?index_name), Cwd), + case Basic of + true -> + TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"), + Bgr = " background=\"" ++ TileFile ++ "\"", + Copyright = + ["<p><font size=\"-1\">\n", + "Copyright © ", year(), + " <a href=\"http://www.erlang.org\">", + "Open Telecom Platform</a><br>\n", + "Updated: <!date>", current_time(), "<!/date>", + "<br>\n</font></p>\n"], + {basic_html, + ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", + "<html>\n", + "<head><title>", TestName1, "</title>\n", + "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", + "</head>\n", + "<body", Bgr, " bgcolor=\"white\" text=\"black\" ", + "link=\"blue\" vlink=\"purple\" alink=\"red\">\n", + LabelStr, "\n"], + ["<center>\n<br><hr><p>\n", + "<a href=\"", AllRuns, + "\">Test run history\n</a> | ", + "<a href=\"", TestIndex, + "\">Top level test index\n</a>\n</p>\n", + Copyright,"</center>\n</body>\n</html>\n"]}; + _ -> + Copyright = + ["<div class=\"copyright\">", + "Copyright © ", year(), + " <a href=\"http://www.erlang.org\">", + "Open Telecom Platform</a><br />\n", + "Updated: <!date>", current_time(), "<!/date>", + "<br />\n</div>\n"], + CSSFile = xhtml(fun() -> "" end, + fun() -> make_relative(locate_default_css_file(), Cwd) end), + {xhtml, + ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n", + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n", + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n", + "<head>\n<title>", TestName1, "</title>\n", + "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", + "<link rel=\"stylesheet\" href=\"", CSSFile, "\" type=\"text/css\">", + "</head>\n","<body>\n", + LabelStr, "\n"], + ["<center>\n<br /><hr /><p>\n", + "<a href=\"", AllRuns, + "\">Test run history\n</a> | ", + "<a href=\"", TestIndex, + "\">Top level test index\n</a>\n</p>\n", + Copyright,"</center>\n</body>\n</html>\n"]} + end. diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl index 233e45248e..8ddb91d355 100644 --- a/lib/common_test/src/ct_make.erl +++ b/lib/common_test/src/ct_make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009. All Rights Reserved. +%% Copyright Ericsson AB 2009-2011. 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 @@ -177,7 +177,7 @@ members([],_MakefileMods,I,Rest) -> {I,Rest}. -%% Any flags that are not recognixed as make flags are passed directly +%% Any flags that are not recognised as make flags are passed directly %% to the compiler. %% So for example make:all([load,debug_info]) will make everything %% with the debug_info flag and load it. diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 877ec9c7dd..05b10bca32 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -33,7 +33,7 @@ %% Exported for VTS --export([run_make/3,do_run/3,tests/1,tests/2,tests/3]). +-export([run_make/3,do_run/4,tests/1,tests/2,tests/3]). %% Misc internal functions @@ -46,15 +46,18 @@ -define(testdir(Name, Suite), ct_util:get_testdir(Name, Suite)). -record(opts, {label, + profile, vts, shell, cover, coverspec, step, logdir, + logopts = [], config = [], event_handlers = [], ct_hooks = [], + enable_builtin_hooks = true, include = [], silent_connections, stylesheet, @@ -156,15 +159,19 @@ script_start(Args) -> end, stop_trace(Tracing), timer:sleep(1000), + io:nl(), Res. script_start1(Parent, Args) -> %% read general start flags Label = get_start_opt(label, fun([Lbl]) -> Lbl end, Args), + Profile = get_start_opt(profile, fun([Prof]) -> Prof end, Args), Vts = get_start_opt(vts, true, Args), Shell = get_start_opt(shell, true, Args), Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args), LogDir = get_start_opt(logdir, fun([LogD]) -> LogD end, Args), + LogOpts = get_start_opt(logopts, fun(Os) -> [list_to_atom(O) || O <- Os] end, + [], Args), MultTT = get_start_opt(multiply_timetraps, fun([MT]) -> list_to_integer(MT) end, 1, Args), ScaleTT = get_start_opt(scale_timetraps, @@ -173,6 +180,10 @@ script_start1(Parent, Args) -> end, false, Args), EvHandlers = event_handler_args2opts(Args), CTHooks = ct_hooks_args2opts(Args), + EnableBuiltinHooks = get_start_opt(enable_builtin_hooks, + fun([CT]) -> list_to_atom(CT); + ([]) -> true + end, true, Args), %% check flags and set corresponding application env variables @@ -234,9 +245,12 @@ script_start1(Parent, Args) -> application:set_env(common_test, basic_html, true) end, - StartOpts = #opts{label = Label, vts = Vts, shell = Shell, cover = Cover, - logdir = LogDir, event_handlers = EvHandlers, + StartOpts = #opts{label = Label, profile = Profile, + vts = Vts, shell = Shell, cover = Cover, + logdir = LogDir, logopts = LogOpts, + event_handlers = EvHandlers, ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = IncludeDirs, silent_connections = SilentConns, stylesheet = Stylesheet, @@ -297,9 +311,15 @@ script_start2(StartOpts = #opts{vts = undefined, Label = choose_val(StartOpts#opts.label, SpecStartOpts#opts.label), + Profile = choose_val(StartOpts#opts.profile, + SpecStartOpts#opts.profile), + LogDir = choose_val(StartOpts#opts.logdir, SpecStartOpts#opts.logdir), + AllLogOpts = merge_vals([StartOpts#opts.logopts, + SpecStartOpts#opts.logopts]), + Cover = choose_val(StartOpts#opts.cover, SpecStartOpts#opts.cover), MultTT = choose_val(StartOpts#opts.multiply_timetraps, @@ -311,18 +331,27 @@ script_start2(StartOpts = #opts{vts = undefined, AllCTHooks = merge_vals( [StartOpts#opts.ct_hooks, SpecStartOpts#opts.ct_hooks]), + + EnableBuiltinHooks = + choose_val( + StartOpts#opts.enable_builtin_hooks, + SpecStartOpts#opts.enable_builtin_hooks), AllInclude = merge_vals([StartOpts#opts.include, SpecStartOpts#opts.include]), application:set_env(common_test, include, AllInclude), {TS,StartOpts#opts{label = Label, + profile = Profile, testspecs = Specs, cover = Cover, logdir = LogDir, + logopts = AllLogOpts, config = SpecStartOpts#opts.config, event_handlers = AllEvHs, ct_hooks = AllCTHooks, + enable_builtin_hooks = + EnableBuiltinHooks, include = AllInclude, multiply_timetraps = MultTT, scale_timetraps = ScaleTT}} @@ -339,9 +368,7 @@ script_start2(StartOpts = #opts{vts = undefined, {[],_} -> {error,no_testspec_specified}; {undefined,_} -> % no testspec used - case check_and_install_configfiles(InitConfig, TheLogDir, - Opts#opts.event_handlers, - Opts#opts.ct_hooks) of + case check_and_install_configfiles(InitConfig, TheLogDir, Opts) of ok -> % go on read tests from start flags script_start3(Opts#opts{config=InitConfig, logdir=TheLogDir}, Args); @@ -351,9 +378,7 @@ script_start2(StartOpts = #opts{vts = undefined, {_,_} -> % testspec used %% merge config from start flags with config from testspec AllConfig = merge_vals([InitConfig, Opts#opts.config]), - case check_and_install_configfiles(AllConfig, TheLogDir, - Opts#opts.event_handlers, - Opts#opts.ct_hooks) of + case check_and_install_configfiles(AllConfig, TheLogDir, Opts) of ok -> % read tests from spec {Run,Skip} = ct_testspec:prepare_tests(Terms, node()), do_run(Run, Skip, Opts#opts{config=AllConfig, @@ -367,9 +392,7 @@ script_start2(StartOpts, Args) -> %% read config/userconfig from start flags InitConfig = ct_config:prepare_config_list(Args), LogDir = which(logdir, StartOpts#opts.logdir), - case check_and_install_configfiles(InitConfig, LogDir, - StartOpts#opts.event_handlers, - StartOpts#opts.ct_hooks) of + case check_and_install_configfiles(InitConfig, LogDir, StartOpts) of ok -> % go on read tests from start flags script_start3(StartOpts#opts{config=InitConfig, logdir=LogDir}, Args); @@ -377,12 +400,17 @@ script_start2(StartOpts, Args) -> Error end. -check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) -> +check_and_install_configfiles( + Configs, LogDir, #opts{ + event_handlers = EvHandlers, + ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks} ) -> case ct_config:check_config_files(Configs) of false -> install([{config,Configs}, {event_handler,EvHandlers}, - {ct_hooks,CTHooks}], LogDir); + {ct_hooks,CTHooks}, + {enable_builtin_hooks,EnableBuiltinHooks}], LogDir); {value,{error,{nofile,File}}} -> {error,{cant_read_config_file,File}}; {value,{error,{wrong_config,Message}}}-> @@ -392,50 +420,72 @@ check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) -> end. script_start3(StartOpts, Args) -> - case proplists:get_value(dir, Args) of - [] -> + StartOpts1 = get_start_opt(step, + fun(Step) -> + StartOpts#opts{step = Step, + cover = undefined} + end, StartOpts, Args), + case {proplists:get_value(dir, Args), + proplists:get_value(suite, Args), + groups_and_cases(proplists:get_value(group, Args), + proplists:get_value(testcase, Args))} of + %% flag specified without data + {_,_,Error={error,_}} -> + Error; + {_,[],_} -> + {error,no_suite_specified}; + {[],_,_} -> {error,no_dir_specified}; - Dirs when is_list(Dirs) -> + + {Dirs,undefined,[]} when is_list(Dirs) -> script_start4(StartOpts#opts{tests = tests(Dirs)}, Args); - undefined -> - case proplists:get_value(suite, Args) of - [] -> - {error,no_suite_specified}; - Suites when is_list(Suites) -> - StartOpts1 = - get_start_opt(step, - fun(Step) -> - StartOpts#opts{step = Step, - cover = undefined} - end, StartOpts, Args), - DirMods = [suite_to_test(S) || S <- Suites], - case groups_and_cases(proplists:get_value(group, Args), - proplists:get_value(testcase, Args)) of - Error = {error,_} -> - Error; - [] when DirMods =/= [] -> - Ts = tests(DirMods), - script_start4(StartOpts1#opts{tests = Ts}, Args); - GroupsAndCases when length(DirMods) == 1 -> - Ts = tests(DirMods, GroupsAndCases), - script_start4(StartOpts1#opts{tests = Ts}, Args); - [_,_|_] when length(DirMods) > 1 -> - {error,multiple_suites_and_cases}; - _ -> - {error,incorrect_suite_option} - end; - undefined -> - if StartOpts#opts.vts ; StartOpts#opts.shell -> - script_start4(StartOpts#opts{tests = []}, Args); - true -> - script_usage(), - {error,incorrect_usage} - end + + {undefined,Suites,[]} when is_list(Suites) -> + Ts = tests([suite_to_test(S) || S <- Suites]), + script_start4(StartOpts1#opts{tests = Ts}, Args); + + {undefined,Suite,GsAndCs} when is_list(Suite) -> + case [suite_to_test(S) || S <- Suite] of + DirMods = [_] -> + Ts = tests(DirMods, GsAndCs), + script_start4(StartOpts1#opts{tests = Ts}, Args); + [_,_|_] -> + {error,multiple_suites_and_cases}; + _ -> + {error,incorrect_start_options} + end; + + {[_,_|_],Suite,[]} when is_list(Suite) -> + {error,multiple_dirs_and_suites}; + + {[Dir],Suite,GsAndCs} when is_list(Dir), is_list(Suite) -> + case [suite_to_test(Dir,S) || S <- Suite] of + DirMods when GsAndCs == [] -> + Ts = tests(DirMods), + script_start4(StartOpts1#opts{tests = Ts}, Args); + DirMods = [_] when GsAndCs /= [] -> + Ts = tests(DirMods, GsAndCs), + script_start4(StartOpts1#opts{tests = Ts}, Args); + [_,_|_] when GsAndCs /= [] -> + {error,multiple_suites_and_cases}; + _ -> + {error,incorrect_start_options} + end; + + {undefined,undefined,GsAndCs} when GsAndCs /= [] -> + {error,incorrect_start_options}; + + {undefined,undefined,_} -> + if StartOpts#opts.vts ; StartOpts#opts.shell -> + script_start4(StartOpts#opts{tests = []}, Args); + true -> + script_usage(), + {error,missing_start_options} end end. script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers, - tests = Tests, logdir = LogDir}, _Args) -> + tests = Tests, logdir = LogDir, logopts = LogOpts}, _Args) -> ConfigFiles = lists:foldl(fun({ct_config_plain,CfgFiles}, AllFiles) when is_list(hd(CfgFiles)) -> @@ -446,25 +496,32 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers, (_, AllFiles) -> AllFiles end, [], Config), - vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), Tests); + vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), LogOpts, Tests); -script_start4(#opts{label = Label, shell = true, config = Config, +script_start4(#opts{label = Label, profile = Profile, + shell = true, config = Config, event_handlers = EvHandlers, ct_hooks = CTHooks, + logopts = LogOpts, + enable_builtin_hooks = EnableBuiltinHooks, logdir = LogDir, testspecs = Specs}, _Args) -> %% label - used by ct_logs application:set_env(common_test, test_label, Label), - InstallOpts = [{config,Config},{event_handler,EvHandlers}, - {ct_hooks, CTHooks}], + %% profile - used in ct_util + application:set_env(common_test, profile, Profile), + if Config == [] -> ok; true -> io:format("\nInstalling: ~p\n\n", [Config]) end, - case install(InstallOpts) of + case install([{config,Config},{event_handler,EvHandlers}, + {ct_hooks, CTHooks}, + {enable_builtin_hooks,EnableBuiltinHooks}]) of ok -> ct_util:start(interactive, LogDir), + ct_util:set_testdata({logopts, LogOpts}), log_ts_names(Specs), io:nl(), ok; @@ -505,6 +562,7 @@ script_usage() -> "\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]" "\n\t[-dir TestDir1 TestDir2 .. TestDirN] |" "\n\t[-suite Suite [-case Case]]" + "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -521,8 +579,9 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" - "\n\t[-event_handler EvHandler1 and EvHandler2 .. EvHandlerN]" - "\n\t[-ct_hooks CTHook1 and CTHook2 .. CTHookN]" + "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" + "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]" + "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -540,8 +599,9 @@ script_usage() -> "\n\t[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]" "\n\t[-stylesheet CSSFile]" "\n\t[-cover CoverCfgFile]" - "\n\t[-event_handler EvHandler1 and EvHandler2 .. EvHandlerN]" - "\n\t[-ct_hooks CTHook1 and CTHook2 .. CTHookN]" + "\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]" + "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]" + "\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]" "\n\t[-include InclDir1 InclDir2 .. InclDirN]" "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" @@ -619,6 +679,16 @@ run_test(StartOpt) when is_tuple(StartOpt) -> run_test([StartOpt]); run_test(StartOpts) when is_list(StartOpts) -> + CTPid = spawn(fun() -> run_test1(StartOpts) end), + Ref = monitor(process, CTPid), + receive + {'DOWN',Ref,process,CTPid,{user_error,Error}} -> + Error; + {'DOWN',Ref,process,CTPid,Other} -> + Other + end. + +run_test1(StartOpts) when is_list(StartOpts) -> case proplists:get_value(refresh_logs, StartOpts) of undefined -> Tracing = start_trace(StartOpts), @@ -627,7 +697,7 @@ run_test(StartOpts) when is_list(StartOpts) -> Res = case ct_repeat:loop_test(func, StartOpts) of false -> - case catch run_test1(StartOpts) of + case catch run_test2(StartOpts) of {'EXIT',Reason} -> file:set_cwd(Cwd), {error,Reason}; @@ -638,20 +708,27 @@ run_test(StartOpts) when is_list(StartOpts) -> Result end, stop_trace(Tracing), - Res; + exit(Res); RefreshDir -> refresh_logs(?abs(RefreshDir)), - ok + exit(done) end. -run_test1(StartOpts) -> +run_test2(StartOpts) -> %% label Label = get_start_opt(label, fun(Lbl) when is_list(Lbl) -> Lbl; (Lbl) when is_atom(Lbl) -> atom_to_list(Lbl) end, StartOpts), + %% profile + Profile = get_start_opt(profile, fun(Prof) when is_list(Prof) -> Prof; + (Prof) when is_atom(Prof) -> atom_to_list(Prof) + end, StartOpts), %% logdir LogDir = get_start_opt(logdir, fun(LD) when is_list(LD) -> LD end, StartOpts), + %% logopts + LogOpts = get_start_opt(logopts, value, [], StartOpts), + %% config & userconfig CfgFiles = ct_config:get_config_file_list(StartOpts), @@ -682,6 +759,11 @@ run_test1(StartOpts) -> %% CT Hooks CTHooks = get_start_opt(ct_hooks, value, [], StartOpts), + EnableBuiltinHooks = get_start_opt(enable_builtin_hooks, + fun(EBH) when EBH == true; + EBH == false -> + EBH + end, true, StartOpts), %% silent connections SilentConns = get_start_opt(silent_connections, @@ -750,10 +832,12 @@ run_test1(StartOpts) -> %% stepped execution Step = get_start_opt(step, value, StartOpts), - Opts = #opts{label = Label, - cover = Cover, step = Step, logdir = LogDir, config = CfgFiles, + Opts = #opts{label = Label, profile = Profile, + cover = Cover, step = Step, logdir = LogDir, + logopts = LogOpts, config = CfgFiles, event_handlers = EvHandlers, ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = Include, silent_connections = SilentConns, stylesheet = Stylesheet, @@ -792,8 +876,12 @@ run_spec_file(Relaxed, SpecOpts = get_data_for_node(TS, node()), Label = choose_val(Opts#opts.label, SpecOpts#opts.label), + Profile = choose_val(Opts#opts.profile, + SpecOpts#opts.profile), LogDir = choose_val(Opts#opts.logdir, SpecOpts#opts.logdir), + AllLogOpts = merge_vals([Opts#opts.logopts, + SpecOpts#opts.logopts]), AllConfig = merge_vals([CfgFiles, SpecOpts#opts.config]), Cover = choose_val(Opts#opts.cover, SpecOpts#opts.cover), @@ -808,24 +896,29 @@ run_spec_file(Relaxed, AllCTHooks = merge_vals([Opts#opts.ct_hooks, SpecOpts#opts.ct_hooks]), + EnableBuiltinHooks = choose_val(Opts#opts.enable_builtin_hooks, + SpecOpts#opts.enable_builtin_hooks), application:set_env(common_test, include, AllInclude), - case check_and_install_configfiles(AllConfig, - which(logdir,LogDir), - AllEvHs, - AllCTHooks) of + Opts1 = Opts#opts{label = Label, + profile = Profile, + cover = Cover, + logdir = which(logdir, LogDir), + logopts = AllLogOpts, + config = AllConfig, + event_handlers = AllEvHs, + include = AllInclude, + testspecs = AbsSpecs, + multiply_timetraps = MultTT, + scale_timetraps = ScaleTT, + ct_hooks = AllCTHooks, + enable_builtin_hooks = EnableBuiltinHooks + }, + + case check_and_install_configfiles(AllConfig,Opts1#opts.logdir, + Opts1) of ok -> - Opts1 = Opts#opts{label = Label, - cover = Cover, - logdir = which(logdir, LogDir), - config = AllConfig, - event_handlers = AllEvHs, - include = AllInclude, - testspecs = AbsSpecs, - multiply_timetraps = MultTT, - scale_timetraps = ScaleTT, - ct_hooks = AllCTHooks}, {Run,Skip} = ct_testspec:prepare_tests(TS, node()), reformat_result(catch do_run(Run, Skip, Opts1, StartOpts)); {error,GCFReason} -> @@ -834,13 +927,10 @@ run_spec_file(Relaxed, end. run_prepared(Run, Skip, Opts = #opts{logdir = LogDir, - config = CfgFiles, - event_handlers = EvHandlers, - ct_hooks = CTHooks}, + config = CfgFiles }, StartOpts) -> LogDir1 = which(logdir, LogDir), - case check_and_install_configfiles(CfgFiles, LogDir1, - EvHandlers, CTHooks) of + case check_and_install_configfiles(CfgFiles, LogDir1, Opts) of ok -> reformat_result(catch do_run(Run, Skip, Opts#opts{logdir = LogDir1}, StartOpts)); @@ -872,7 +962,8 @@ check_config_file(Callback, File)-> run_dir(Opts = #opts{logdir = LogDir, config = CfgFiles, event_handlers = EvHandlers, - ct_hooks = CTHook }, StartOpts) -> + ct_hooks = CTHook, + enable_builtin_hooks = EnableBuiltinHooks }, StartOpts) -> LogDir1 = which(logdir, LogDir), Opts1 = Opts#opts{logdir = LogDir1}, AbsCfgFiles = @@ -895,71 +986,107 @@ run_dir(Opts = #opts{logdir = LogDir, end, CfgFiles), case install([{config,AbsCfgFiles}, {event_handler,EvHandlers}, - {ct_hooks, CTHook}], LogDir1) of + {ct_hooks, CTHook}, + {enable_builtin_hooks,EnableBuiltinHooks}], LogDir1) of ok -> ok; {error,IReason} -> exit(IReason) end, - case lists:keysearch(dir, 1, StartOpts) of - {value,{_,Dirs=[Dir|_]}} when not is_integer(Dir), - length(Dirs)>1 -> - %% multiple dirs (no suite) - reformat_result(catch do_run(tests(Dirs), [], Opts1, StartOpts)); - false -> % no dir - %% fun for converting suite name to {Dir,Mod} tuple - S2M = fun(S) when is_list(S) -> - {filename:dirname(S), - list_to_atom(filename:rootname(filename:basename(S)))}; - (A) -> - {".",A} - end, - case lists:keysearch(suite, 1, StartOpts) of - {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) -> - {Dir,Mod} = S2M(Suite), - case groups_and_cases(proplists:get_value(group, StartOpts), - proplists:get_value(testcase, StartOpts)) of - Error = {error,_} -> - exit(Error); + case {proplists:get_value(dir, StartOpts), + proplists:get_value(suite, StartOpts), + groups_and_cases(proplists:get_value(group, StartOpts), + proplists:get_value(testcase, StartOpts))} of + %% flag specified without data + {_,_,Error={error,_}} -> + Error; + {_,[],_} -> + {error,no_suite_specified}; + {[],_,_} -> + {error,no_dir_specified}; + + {Dirs=[Hd|_],undefined,[]} when is_list(Dirs), not is_integer(Hd) -> + Dirs1 = [if is_atom(D) -> atom_to_list(D); + true -> D end || D <- Dirs], + reformat_result(catch do_run(tests(Dirs1), [], Opts1, StartOpts)); + + {Dir=[Hd|_],undefined,[]} when is_list(Dir) and is_integer(Hd) -> + reformat_result(catch do_run(tests(Dir), [], Opts1, StartOpts)); + + {Dir,undefined,[]} when is_atom(Dir) and (Dir /= undefined) -> + reformat_result(catch do_run(tests(atom_to_list(Dir)), + [], Opts1, StartOpts)); + + {undefined,Suites=[Hd|_],[]} when not is_integer(Hd) -> + Suites1 = [suite_to_test(S) || S <- Suites], + reformat_result(catch do_run(tests(Suites1), [], Opts1, StartOpts)); + + {undefined,Suite,[]} when is_atom(Suite) and + (Suite /= undefined) -> + {Dir,Mod} = suite_to_test(Suite), + reformat_result(catch do_run(tests(Dir, Mod), [], Opts1, StartOpts)); + + {undefined,Suite,GsAndCs} when is_atom(Suite) and + (Suite /= undefined) -> + {Dir,Mod} = suite_to_test(Suite), + reformat_result(catch do_run(tests(Dir, Mod, GsAndCs), + [], Opts1, StartOpts)); + + {undefined,[Hd,_|_],_GsAndCs} when not is_integer(Hd) -> + exit(multiple_suites_and_cases); + + {undefined,Suite=[Hd|Tl],GsAndCs} when is_integer(Hd) ; + (is_list(Hd) and (Tl == [])) ; + (is_atom(Hd) and (Tl == [])) -> + {Dir,Mod} = suite_to_test(Suite), + reformat_result(catch do_run(tests(Dir, Mod, GsAndCs), + [], Opts1, StartOpts)); + + {[Hd,_|_],_Suites,[]} when is_list(Hd) ; not is_integer(Hd) -> + exit(multiple_dirs_and_suites); + + {undefined,undefined,GsAndCs} when GsAndCs /= [] -> + exit(incorrect_start_options); + + {Dir,Suite,GsAndCs} when is_integer(hd(Dir)) ; + (is_atom(Dir) and (Dir /= undefined)) ; + ((length(Dir) == 1) and is_atom(hd(Dir))) ; + ((length(Dir) == 1) and is_list(hd(Dir))) -> + Dir1 = if is_atom(Dir) -> atom_to_list(Dir); + true -> Dir end, + if Suite == undefined -> + exit(incorrect_start_options); + + is_integer(hd(Suite)) ; + (is_atom(Suite) and (Suite /= undefined)) ; + ((length(Suite) == 1) and is_atom(hd(Suite))) ; + ((length(Suite) == 1) and is_list(hd(Suite))) -> + {Dir2,Mod} = suite_to_test(Dir1, Suite), + case GsAndCs of [] -> - reformat_result(catch do_run(tests(Dir, listify(Mod)), + reformat_result(catch do_run(tests(Dir2, Mod), [], Opts1, StartOpts)); - GsAndCs -> - reformat_result(catch do_run(tests(Dir, Mod, GsAndCs), + _ -> + reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs), [], Opts1, StartOpts)) end; - {value,{_,Suites}} -> - reformat_result(catch do_run(tests(lists:map(S2M, Suites)), - [], Opts1, StartOpts)); - _ -> - exit(no_tests_specified) - end; - {value,{_,Dir}} -> - case lists:keysearch(suite, 1, StartOpts) of - {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) -> - Mod = if is_atom(Suite) -> Suite; - true -> list_to_atom(Suite) - end, - case groups_and_cases(proplists:get_value(group, StartOpts), - proplists:get_value(testcase, StartOpts)) of - Error = {error,_} -> - exit(Error); - [] -> - reformat_result(catch do_run(tests(Dir, listify(Mod)), + + is_list(Suite) -> % multiple suites + case [suite_to_test(Dir1, S) || S <- Suite] of + [_,_|_] when GsAndCs /= [] -> + exit(multiple_suites_and_cases); + [{Dir2,Mod}] when GsAndCs /= [] -> + reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs), [], Opts1, StartOpts)); - GsAndCs -> - reformat_result(catch do_run(tests(Dir, Mod, GsAndCs), + DirMods -> + reformat_result(catch do_run(tests(DirMods), [], Opts1, StartOpts)) - end; - {value,{_,Suites=[Suite|_]}} when is_list(Suite) -> - Mods = lists:map(fun(Str) -> list_to_atom(Str) end, Suites), - reformat_result(catch do_run(tests(delistify(Dir), Mods), - [], Opts1, StartOpts)); - {value,{_,Suites}} -> - reformat_result(catch do_run(tests(delistify(Dir), Suites), - [], Opts1, StartOpts)); - false -> % no suite, only dir - reformat_result(catch do_run(tests(listify(Dir)), - [], Opts1, StartOpts)) - end + end + end; + + {undefined,undefined,[]} -> + exit(no_test_specified); + + {Dir,Suite,GsAndCs} -> + exit({incorrect_start_options,{Dir,Suite,GsAndCs}}) end. %%%----------------------------------------------------------------- @@ -970,19 +1097,38 @@ run_dir(Opts = #opts{logdir = LogDir, %%% the same as those used in test specification files. %%% @equiv ct:run_testspec/1 %%%----------------------------------------------------------------- - run_testspec(TestSpec) -> + CTPid = spawn(fun() -> run_testspec1(TestSpec) end), + Ref = monitor(process, CTPid), + receive + {'DOWN',Ref,process,CTPid,{user_error,Error}} -> + Error; + {'DOWN',Ref,process,CTPid,Other} -> + Other + end. + +run_testspec1(TestSpec) -> {ok,Cwd} = file:get_cwd(), io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]), - case catch run_testspec1(TestSpec) of + case catch run_testspec2(TestSpec) of {'EXIT',Reason} -> file:set_cwd(Cwd), - {error,Reason}; + exit({error,Reason}); Result -> - Result + exit(Result) end. -run_testspec1(TestSpec) -> +run_testspec2(File) when is_list(File), is_integer(hd(File)) -> + case file:read_file_info(File) of + {ok,_} -> + exit("Bad argument, " + "use ct:run_test([{spec," ++ File ++ "}])"); + _ -> + exit("Bad argument, list of tuples expected, " + "use ct:run_test/1 for test specification files") + end; + +run_testspec2(TestSpec) -> case catch ct_testspec:collect_tests_from_list(TestSpec, false) of {E,CTReason} when E == error ; E == 'EXIT' -> exit(CTReason); @@ -999,9 +1145,8 @@ run_testspec1(TestSpec) -> end, application:set_env(common_test, include, AllInclude), LogDir1 = which(logdir,Opts#opts.logdir), - case check_and_install_configfiles(Opts#opts.config, LogDir1, - Opts#opts.event_handlers, - Opts#opts.ct_hooks) of + case check_and_install_configfiles( + Opts#opts.config, LogDir1, Opts) of ok -> Opts1 = Opts#opts{testspecs = [], logdir = LogDir1, @@ -1014,20 +1159,28 @@ run_testspec1(TestSpec) -> end. get_data_for_node(#testspec{label = Labels, + profile = Profiles, logdir = LogDirs, + logopts = LogOptsList, cover = CoverFs, config = Cfgs, userconfig = UsrCfgs, event_handler = EvHs, ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = Incl, multiply_timetraps = MTs, scale_timetraps = STs}, Node) -> Label = proplists:get_value(Node, Labels), + Profile = proplists:get_value(Node, Profiles), LogDir = case proplists:get_value(Node, LogDirs) of undefined -> "."; Dir -> Dir end, + LogOpts = case proplists:get_value(Node, LogOptsList) of + undefined -> []; + LOs -> LOs + end, Cover = proplists:get_value(Node, CoverFs), MT = proplists:get_value(Node, MTs), ST = proplists:get_value(Node, STs), @@ -1037,11 +1190,14 @@ get_data_for_node(#testspec{label = Labels, FiltCTHooks = [Hook || {N,Hook} <- CTHooks, N==Node], Include = [I || {N,I} <- Incl, N==Node], #opts{label = Label, + profile = Profile, logdir = LogDir, + logopts = LogOpts, cover = Cover, config = ConfigFiles, event_handlers = EvHandlers, ct_hooks = FiltCTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = Include, multiply_timetraps = MT, scale_timetraps = ST}. @@ -1118,8 +1274,24 @@ reformat_result({user_error,Reason}) -> reformat_result(Result) -> Result. -suite_to_test(Suite) -> - {filename:dirname(Suite),list_to_atom(filename:rootname(filename:basename(Suite)))}. +suite_to_test(Suite) when is_atom(Suite) -> + suite_to_test(atom_to_list(Suite)); + +suite_to_test(Suite) when is_list(Suite) -> + {filename:dirname(Suite), + list_to_atom(filename:rootname(filename:basename(Suite)))}. + +suite_to_test(Dir, Suite) when is_atom(Suite) -> + suite_to_test(Dir, atom_to_list(Suite)); + +suite_to_test(Dir, Suite) when is_list(Suite) -> + case filename:dirname(Suite) of + "." -> + {Dir,list_to_atom(filename:rootname(Suite))}; + DirName -> % ignore Dir + File = filename:basename(Suite), + {DirName,list_to_atom(filename:rootname(File))} + end. groups_and_cases(Gs, Cs) when ((Gs == undefined) or (Gs == [])) and ((Cs == undefined) or (Cs == [])) -> @@ -1153,9 +1325,11 @@ tests(TestDirs) when is_list(TestDirs), is_list(hd(TestDirs)) -> [{?testdir(TestDir,all),all,all} || TestDir <- TestDirs]. do_run(Tests, Misc) when is_list(Misc) -> - do_run(Tests, Misc, "."). + do_run(Tests, Misc, ".", []). -do_run(Tests, Misc, LogDir) when is_list(Misc) -> +do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc), + is_list(LogDir), + is_list(LogOpts) -> Opts = case proplists:get_value(step, Misc) of undefined -> @@ -1170,11 +1344,10 @@ do_run(Tests, Misc, LogDir) when is_list(Misc) -> CoverFile -> Opts#opts{cover = CoverFile} end, - do_run(Tests, [], Opts1#opts{logdir = LogDir}, []). - -do_run(Tests, Skip, Opts, Args) -> - #opts{label = Label, cover = Cover} = Opts, + do_run(Tests, [], Opts1#opts{logdir = LogDir}, []); +do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> + #opts{label = Label, profile = Profile, cover = Cover} = Opts, %% label - used by ct_logs TestLabel = if Label == undefined -> undefined; @@ -1184,6 +1357,15 @@ do_run(Tests, Skip, Opts, Args) -> end, application:set_env(common_test, test_label, TestLabel), + %% profile - used in ct_util + TestProfile = + if Profile == undefined -> undefined; + is_atom(Profile) -> atom_to_list(Profile); + is_list(Profile) -> Profile; + true -> undefined + end, + application:set_env(common_test, profile, TestProfile), + case code:which(test_server) of non_existing -> exit({error,no_path_to_test_server}); @@ -1218,6 +1400,8 @@ do_run(Tests, Skip, Opts, Args) -> _Pid -> %% save stylesheet info ct_util:set_testdata({stylesheet,Opts#opts.stylesheet}), + %% save logopts + ct_util:set_testdata({logopts,Opts#opts.logopts}), %% enable silent connections case Opts#opts.silent_connections of [] -> @@ -1476,6 +1660,14 @@ final_tests1([{TestDir,Suite,GrsOrCs}|Tests], Final, Skip, Bad) when ({skipped,Group,TCs}) -> [ct_framework:make_conf(TestDir, Suite, Group, [skipped], TCs)]; + ({GrSpec = {Group,_},TCs}) -> + Props = [{override,GrSpec}], + [ct_framework:make_conf(TestDir, Suite, + Group, Props, TCs)]; + ({GrSpec = {Group,_,_},TCs}) -> + Props = [{override,GrSpec}], + [ct_framework:make_conf(TestDir, Suite, + Group, Props, TCs)]; ({Group,TCs}) -> [ct_framework:make_conf(TestDir, Suite, Group, [], TCs)]; @@ -1985,7 +2177,14 @@ maybe_interpret1(Suite, Cases, StepOpts) when is_list(Cases) -> maybe_interpret2(Suite, Cases, StepOpts) -> set_break_on_config(Suite, StepOpts), - [i:ib(Suite, Case, 1) || Case <- Cases], + [begin try i:ib(Suite, Case, 1) of + _ -> ok + catch + _:_Error -> + io:format(user, "Invalid breakpoint: ~w:~w/1~n", + [Suite,Case]) + end + end || Case <- Cases, is_atom(Case)], test_server_ctrl:multiply_timetraps(infinity), WinOp = case lists:member(keep_inactive, ensure_atom(StepOpts)) of true -> no_kill; @@ -1998,10 +2197,18 @@ maybe_interpret2(Suite, Cases, StepOpts) -> set_break_on_config(Suite, StepOpts) -> case lists:member(config, ensure_atom(StepOpts)) of true -> - i:ib(Suite, init_per_suite, 1), - i:ib(Suite, init_per_testcase, 2), - i:ib(Suite, end_per_testcase, 2), - i:ib(Suite, end_per_suite, 1); + SetBPIfExists = fun(F,A) -> + case erlang:function_exported(Suite, F, A) of + true -> i:ib(Suite, F, A); + false -> ok + end + end, + SetBPIfExists(init_per_suite, 1), + SetBPIfExists(init_per_group, 2), + SetBPIfExists(init_per_testcase, 2), + SetBPIfExists(end_per_testcase, 2), + SetBPIfExists(end_per_group, 2), + SetBPIfExists(end_per_suite, 1); false -> ok end. @@ -2055,6 +2262,15 @@ get_start_opt(Key, IfExists, Args) -> get_start_opt(Key, IfExists, undefined, Args). get_start_opt(Key, IfExists, IfNotExists, Args) -> + try try_get_start_opt(Key, IfExists, IfNotExists, Args) of + Result -> + Result + catch + error:_ -> + exit({user_error,{bad_argument,Key}}) + end. + +try_get_start_opt(Key, IfExists, IfNotExists, Args) -> case lists:keysearch(Key, 1, Args) of {value,{Key,Val}} when is_function(IfExists) -> IfExists(Val); @@ -2067,8 +2283,11 @@ get_start_opt(Key, IfExists, IfNotExists, Args) -> end. ct_hooks_args2opts(Args) -> - ct_hooks_args2opts( - proplists:get_value(ct_hooks, Args, []),[]). + lists:foldl(fun({ct_hooks,Hooks}, Acc) -> + ct_hooks_args2opts(Hooks,Acc); + (_,Acc) -> + Acc + end,[],Args). ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) -> ct_hooks_args2opts(Rest,[{list_to_atom(CTH), @@ -2226,6 +2445,8 @@ opts2args(EnvStartOpts) -> end, EHs), [_LastAnd|StrsR] = lists:reverse(lists:flatten(Strs)), [{event_handler_init,lists:reverse(StrsR)}]; + ({logopts,LOs}) when is_list(LOs) -> + [{logopts,[atom_to_list(LO) || LO <- LOs]}]; ({ct_hooks,[]}) -> []; ({ct_hooks,CTHs}) when is_list(CTHs) -> @@ -2289,32 +2510,31 @@ is_suite(ModOrFile) when is_list(ModOrFile) -> end. get_all_testcases(Suite) -> - %%! this needs to be updated to handle testcase groups later!! - case catch Suite:all() of - {'EXIT',Why} -> - {error,Why}; - {skip,_} -> - []; - Cases -> - AllCases = - lists:foldl(fun({sequence,SeqName}, All) -> - case catch Suite:sequences() of - {'EXIT',_} -> - All; - Seqs -> - case proplists:get_value(SeqName, Seqs) of - undefined -> - All; - SeqCases -> - lists:reverse(SeqCases) ++ All - end - end; - (Case,All) -> - [Case|All] - end, [], Cases), - lists:reverse(AllCases) + try ct_framework:get_all_cases(Suite) of + {error,_Reason} = Error -> + Error; + SuiteCases -> + Cases = [C || {_S,C} <- SuiteCases], + try Suite:sequences() of + [] -> + Cases; + Seqs -> + TCs1 = lists:flatten([TCs || {_,TCs} <- Seqs]), + lists:reverse( + lists:foldl(fun(TC, Acc) -> + case lists:member(TC, Acc) of + true -> Acc; + false -> [TC | Acc] + end + end, [], Cases ++ TCs1)) + catch + _:_ -> + Cases + end + catch + _:Error -> + {error,Error} end. - %% Internal tracing support. If {ct_trace,TraceSpec} is present, the %% TraceSpec file will be consulted and dbg used to trace function @@ -2335,8 +2555,8 @@ start_trace(Args) -> false end; {_,Error} -> - io:format("Warning! Tracing not started. Reason: ~p~n~n", - [Error]), + io:format("Warning! Tracing not started. Reason: ~s~n~n", + [file:format_error(Error)]), false end; false -> diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl index c6f5fd7df4..f4a551e3ff 100644 --- a/lib/common_test/src/ct_telnet.erl +++ b/lib/common_test/src/ct_telnet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2011. 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 @@ -245,7 +245,6 @@ cmdf(Connection,CmdFormat,Args) -> %%% Data = [string()] %%% @doc Send a telnet command and wait for prompt %%% (uses a format string and list of arguments to build the command). -%%%----------------------------------------------------------------- cmdf(Connection,CmdFormat,Args,Timeout) when is_list(Args) -> Cmd = lists:flatten(io_lib:format(CmdFormat,Args)), cmd(Connection,Cmd,Timeout). @@ -360,15 +359,15 @@ expect(Connection,Patterns) -> %%% will also be a <code>HaltReason</code> returned.</p> %%% %%% <p><underline>Examples:</underline><br/> -%%% <code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}], -%%% [sequence,{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match +%%% <code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code> +%%% <code>[sequence,{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match %%% "ABC" first and then "XYZ", but if "NNN" appears the function will %%% return <code>{error,{nnn,["NNN"]}}</code>. If both "ABC" and "XYZ" %%% are matched, the function will return %%% <code>{ok,[AbcMatch,XyzMatch]}</code>.</p> %%% -%%% <p><code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}], -%%% [{repeat,2},{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match +%%% <p><code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code> +%%% <code>[{repeat,2},{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match %%% "ABC" or "XYZ" twice. If "NNN" appears the function will return %%% with <code>HaltReason = {nnn,["NNN"]}</code>.</p> %%% diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index d845358bb2..b68cbd3aa1 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -249,11 +249,15 @@ collect_tests_from_file1([Spec|Specs],TestSpec,Relaxed) -> SpecDir = filename:dirname(filename:absname(Spec)), case file:consult(Spec) of {ok,Terms} -> - TestSpec1 = collect_tests(Terms,TestSpec#testspec{spec_dir=SpecDir}, + TestSpec1 = collect_tests(Terms, + TestSpec#testspec{spec_dir=SpecDir}, Relaxed), collect_tests_from_file1(Specs,TestSpec1,Relaxed); {error,Reason} -> - throw({error,{Spec,Reason}}) + ReasonStr = + lists:flatten(io_lib:format("~s", + [file:format_error(Reason)])), + throw({error,{Spec,ReasonStr}}) end; collect_tests_from_file1([],TS=#testspec{config=Cfgs,event_handler=EvHs, include=Incl,tests=Tests},_) -> @@ -481,6 +485,26 @@ add_tests([{logdir,Node,Dir}|Ts],Spec) -> add_tests([{logdir,Dir}|Ts],Spec) -> add_tests([{logdir,all_nodes,Dir}|Ts],Spec); +%% --- logopts --- +add_tests([{logopts,all_nodes,Opts}|Ts],Spec) -> + LogOpts = Spec#testspec.logopts, + Tests = [{logopts,N,Opts} || + N <- list_nodes(Spec), + lists:keymember(ref2node(N,Spec#testspec.nodes),1, + LogOpts) == false], + add_tests(Tests++Ts,Spec); +add_tests([{logopts,Nodes,Opts}|Ts],Spec) when is_list(Nodes) -> + Ts1 = separate(Nodes,logopts,[Opts],Ts,Spec#testspec.nodes), + add_tests(Ts1,Spec); +add_tests([{logopts,Node,Opts}|Ts],Spec) -> + LogOpts = Spec#testspec.logopts, + LogOpts1 = [{ref2node(Node,Spec#testspec.nodes),Opts} | + lists:keydelete(ref2node(Node,Spec#testspec.nodes), + 1,LogOpts)], + add_tests(Ts,Spec#testspec{logopts=LogOpts1}); +add_tests([{logopts,Opts}|Ts],Spec) -> + add_tests([{logopts,all_nodes,Opts}|Ts],Spec); + %% --- label --- add_tests([{label,all_nodes,Lbl}|Ts],Spec) -> Labels = Spec#testspec.label, @@ -646,6 +670,10 @@ add_tests([{ct_hooks, _Node, []}|Ts], Spec) -> add_tests([{ct_hooks, Hooks}|Ts], Spec) -> add_tests([{ct_hooks, all_nodes, Hooks}|Ts], Spec); +%% -- enable_builtin_hooks -- +add_tests([{enable_builtin_hooks,Bool}|Ts],Spec) -> + add_tests(Ts, Spec#testspec{ enable_builtin_hooks = Bool }); + %% --- include --- add_tests([{include,all_nodes,InclDirs}|Ts],Spec) -> Tests = lists:map(fun(N) -> {include,N,InclDirs} end, list_nodes(Spec)), @@ -850,7 +878,11 @@ separate([],_,_,_) -> %% {Suite2,[GrOrCase21,GrOrCase22,...]},...]} %% {{Node,Dir},[{Suite1,{skip,Cmt}}, %% {Suite2,[{GrOrCase21,{skip,Cmt}},GrOrCase22,...]},...]} -%% GrOrCase = {GroupName,[Case1,Case2,...]} | Case +%% GrOrCase = {GroupSpec,[Case1,Case2,...]} | Case +%% GroupSpec = {GroupName,OverrideProps} | +%% {GroupName,OverrideProps,SubGroupSpec} +%% OverrideProps = Props | default +%% SubGroupSpec = GroupSpec | [] insert_suites(Node,Dir,[S|Ss],Tests, MergeTests) -> Tests1 = insert_cases(Node,Dir,S,all,Tests,MergeTests), @@ -861,7 +893,7 @@ insert_suites(Node,Dir,S,Tests,MergeTests) -> insert_suites(Node,Dir,[S],Tests,MergeTests). insert_groups(Node,Dir,Suite,Group,Cases,Tests,MergeTests) - when is_atom(Group) -> + when is_atom(Group); is_tuple(Group) -> insert_groups(Node,Dir,Suite,[Group],Cases,Tests,MergeTests); insert_groups(Node,Dir,Suite,Groups,Cases,Tests,false) when ((Cases == all) or is_list(Cases)) and is_list(Groups) -> @@ -1097,6 +1129,8 @@ valid_terms() -> {merge_tests,1}, {logdir,2}, {logdir,3}, + {logopts,2}, + {logopts,3}, {label,2}, {label,3}, {event_handler,2}, @@ -1104,6 +1138,7 @@ valid_terms() -> {event_handler,4}, {ct_hooks,2}, {ct_hooks,3}, + {enable_builtin_hooks,1}, {multiply_timetraps,2}, {multiply_timetraps,3}, {scale_timetraps,2}, diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index b3e345b4e5..3b6ad6f98d 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -47,7 +47,7 @@ -export([get_mode/0, create_table/3, read_opts/0]). --export([set_cwd/1, reset_cwd/0]). +-export([set_cwd/1, reset_cwd/0, get_start_dir/0]). -export([parse_table/1]). @@ -61,6 +61,9 @@ -export([warn_duplicates/1]). +-export([get_profile_data/0, get_profile_data/1, + get_profile_data/2, open_url/3]). + -include("ct_event.hrl"). -include("ct_util.hrl"). @@ -121,13 +124,15 @@ do_start(Parent,Mode,LogDir) -> ok -> ok; E -> exit(E) end, + DoExit = fun(Reason) -> file:set_cwd(StartDir), exit(Reason) end, Opts = case read_opts() of {ok,Opts1} -> Opts1; Error -> Parent ! {self(),Error}, - exit(Error) + DoExit(Error) end, + %% start an event manager (if not already started by master) case ct_event:start_link() of {error,{already_started,_}} -> @@ -140,16 +145,23 @@ do_start(Parent,Mode,LogDir) -> ct_event:add_handler([{vts,VtsPid}]) end end, + %% start ct_config server - ct_config:start(Mode), + try ct_config:start(Mode) of + _ -> ok + catch + _Class:CfgError -> + DoExit(CfgError) + end, + %% add user event handlers case lists:keysearch(event_handler,1,Opts) of {value,{_,Handlers}} -> Add = fun({H,Args}) -> case catch gen_event:add_handler(?CT_EVMGR_REF,H,Args) of ok -> ok; - {'EXIT',Why} -> exit(Why); - Other -> exit({event_handler,Other}) + {'EXIT',Why} -> DoExit(Why); + Other -> DoExit({event_handler,Other}) end end, case catch lists:foreach(Add,Handlers) of @@ -168,10 +180,15 @@ do_start(Parent,Mode,LogDir) -> data={StartTime, lists:flatten(TestLogDir)}}), %% Initialize ct_hooks - case catch ct_hooks:init(Opts) of + try ct_hooks:init(Opts) of ok -> Parent ! {self(),started}; - {_,CTHReason} -> + {fail,CTHReason} -> + ct_logs:tc_print('Suite Callback',CTHReason,[]), + self() ! {{stop,{self(),{user_error,CTHReason}}}, + {Parent,make_ref()}} + catch + _:CTHReason -> ct_logs:tc_print('Suite Callback',CTHReason,[]), self() ! {{stop,{self(),{user_error,CTHReason}}}, {Parent,make_ref()}} @@ -243,6 +260,9 @@ set_cwd(Dir) -> reset_cwd() -> call(reset_cwd). +get_start_dir() -> + call(get_start_dir). + loop(Mode,TestData,StartDir) -> receive {update_last_run_index,From} -> @@ -319,6 +339,9 @@ loop(Mode,TestData,StartDir) -> {reset_cwd,From} -> return(From,file:set_cwd(StartDir)), loop(From,TestData,StartDir); + {get_start_dir,From} -> + return(From,StartDir), + loop(From,TestData,StartDir); {{stop,Info},From} -> Time = calendar:local_time(), ct_event:sync_notify(#event{name=test_done, @@ -332,7 +355,7 @@ loop(Mode,TestData,StartDir) -> ets:delete(?conn_table), ets:delete(?board_table), ets:delete(?suite_table), - ct_logs:close(Info), + ct_logs:close(Info, StartDir), ct_event:stop(), ct_config:stop(), file:set_cwd(StartDir), @@ -727,6 +750,79 @@ warn_duplicates(Suites) -> lists:foreach(Warn, Suites), ok. +%%%----------------------------------------------------------------- +%%% @spec +%%% +%%% @doc +get_profile_data() -> + get_profile_data(all). + +get_profile_data(KeyOrStartDir) -> + if is_atom(KeyOrStartDir) -> + get_profile_data(KeyOrStartDir, get_start_dir()); + is_list(KeyOrStartDir) -> + get_profile_data(all, KeyOrStartDir) + end. + +get_profile_data(Key, StartDir) -> + Profile = case application:get_env(common_test, profile) of + {ok,undefined} -> default; + {ok,Prof} -> Prof; + _ -> default + end, + get_profile_data(Profile, Key, StartDir). + +get_profile_data(Profile, Key, StartDir) -> + File = case Profile of + default -> + ?ct_profile_file; + _ when is_list(Profile) -> + ?ct_profile_file ++ "." ++ Profile; + _ when is_atom(Profile) -> + ?ct_profile_file ++ "." ++ atom_to_list(Profile) + end, + FullNameWD = filename:join(StartDir, File), + {WhichFile,Result} = + case file:consult(FullNameWD) of + {error,enoent} -> + case init:get_argument(home) of + {ok,[[HomeDir]]} -> + FullNameHome = filename:join(HomeDir, File), + {FullNameHome,file:consult(FullNameHome)}; + _ -> + {File,{error,enoent}} + end; + Consulted -> + {FullNameWD,Consulted} + end, + case Result of + {error,enoent} when Profile /= default -> + io:format(user, "~nERROR! Missing profile file ~p~n", [File]), + undefined; + {error,enoent} when Profile == default -> + undefined; + {error,Reason} -> + io:format(user,"~nERROR! Error in profile file ~p: ~p~n", + [WhichFile,Reason]), + undefined; + {ok,Data} -> + Data1 = case Data of + [List] when is_list(List) -> + List; + _ when is_list(Data) -> + Data; + _ -> + io:format(user, + "~nERROR! Invalid profile data in ~p~n", + [WhichFile]), + [] + end, + if Key == all -> + Data1; + true -> + proplists:get_value(Key, Data) + end + end. %%%----------------------------------------------------------------- %%% Internal functions @@ -799,3 +895,28 @@ abs_name2([H|T],Acc) -> abs_name2(T,[H|Acc]); abs_name2([],Acc) -> filename:join(lists:reverse(Acc)). + +open_url(iexplore, Args, URL) -> + {ok,R} = win32reg:open([read]), + ok = win32reg:change_key(R,"applications\\iexplore.exe\\shell\\open\\command"), + case win32reg:values(R) of + {ok, Paths} -> + Path = proplists:get_value(default, Paths), + [Cmd | _] = string:tokens(Path, "%"), + Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL, + io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd1]), + open_port({spawn,Cmd1}, []); + _ -> + io:format("~nNo path to iexplore.exe~n",[]) + end, + win32reg:close(R), + ok; + +open_url(Prog, Args, URL) -> + ProgStr = if is_atom(Prog) -> atom_to_list(Prog); + is_list(Prog) -> Prog + end, + Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL, + io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd]), + open_port({spawn,Cmd},[]), + ok. diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index 556f88c84d..bde832811a 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -31,12 +31,15 @@ nodes=[], init=[], label=[], + profile=[], logdir=["."], + logopts=[], cover=[], config=[], userconfig=[], event_handler=[], ct_hooks=[], + enable_builtin_hooks=true, include=[], multiply_timetraps=[], scale_timetraps=[], @@ -58,3 +61,5 @@ -define(missing_suites_info, "missing_suites.info"). -define(ct_config_txt, ct_config_plain). + +-define(ct_profile_file, ".common_test"). diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl new file mode 100644 index 0000000000..14663b7738 --- /dev/null +++ b/lib/common_test/src/cth_log_redirect.erl @@ -0,0 +1,111 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011. 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(cth_log_redirect). + +%%% @doc Common Test Framework functions handling test specifications. +%%% +%%% <p>This module redirects sasl and error logger info to common test log.</p> +%%% @end + + +%% CTH Callbacks +-export([id/1, init/2, post_init_per_group/4, pre_end_per_group/3, + post_end_per_testcase/4]). + +%% Event handler Callbacks +-export([init/1, + handle_event/2, handle_call/2, handle_info/2, + terminate/2]). + +id(_Opts) -> + ?MODULE. + +init(?MODULE, _Opts) -> + error_logger:add_report_handler(?MODULE), + tc_log. + +post_init_per_group(Group, Config, Result, tc_log) -> + case lists:member(parallel,proplists:get_value( + tc_group_properties,Config,[])) of + true -> + {Result, {set_log_func(ct_log),Group}}; + false -> + {Result, tc_log} + end; +post_init_per_group(_Group, _Config, Result, State) -> + {Result, State}. + +post_end_per_testcase(_TC, _Config, Result, State) -> + %% Make sure that the event queue is flushed + %% before ending this test case. + gen_event:call(error_logger, ?MODULE, flush), + {Result, State}. + +pre_end_per_group(Group, Config, {ct_log, Group}) -> + {Config, set_log_func(tc_log)}; +pre_end_per_group(_Group, Config, State) -> + {Config, State}. + + +%% Copied and modified from sasl_report_tty_h.erl +init(_Type) -> + {ok, tc_log}. + +handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() -> + {ok, State}; +handle_event(Event, LogFunc) -> + case lists:keyfind(sasl, 1, application:which_applications()) of + false -> + sasl_not_started; + _Else -> + {ok, ErrLogType} = application:get_env(sasl, errlog_type), + SReport = sasl_report:format_report(group_leader(), ErrLogType, + tag_event(Event)), + if is_list(SReport) -> + ct_logs:LogFunc(sasl, SReport, []); + true -> %% Report is an atom if no logging is to be done + ignore + end + end, + EReport = error_logger_tty_h:write_event( + tag_event(Event),io_lib), + if is_list(EReport) -> + ct_logs:LogFunc(error_logger, EReport, []); + true -> %% Report is an atom if no logging is to be done + ignore + end, + {ok, LogFunc}. + + +handle_info(_,State) -> {ok, State}. + +handle_call(flush,State) -> + {ok, ok, State}; +handle_call({set_logfunc,NewLogFunc},_) -> + {ok, NewLogFunc, NewLogFunc}; +handle_call(_Query, _State) -> {error, bad_query}. + +terminate(_Reason, _Type) -> + []. + +tag_event(Event) -> + {calendar:local_time(), Event}. + +set_log_func(Func) -> + gen_event:call(error_logger, ?MODULE, {set_logfunc, Func}). diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl index f0bf090804..cc8a932887 100644 --- a/lib/common_test/src/vts.erl +++ b/lib/common_test/src/vts.erl @@ -20,7 +20,7 @@ -module(vts). -export([start/0, - init_data/4, + init_data/5, stop/0, report/2]). @@ -32,6 +32,7 @@ menu_frame/2, welcome_frame/2, config_frame/2, + browse_config_file/2, add_config_file/2, remove_config_file/2, run_frame/2, @@ -56,7 +57,7 @@ -record(state,{tests=[],config=[],event_handler=[],test_runner, running=0,reload_results=false,start_dir,current_log_dir, - total=0,ok=0,fail=0,skip=0,testruns=[]}). + logopts=[],total=0,ok=0,fail=0,skip=0,testruns=[]}). %%%----------------------------------------------------------------- @@ -65,8 +66,8 @@ start() -> webtool:start(), webtool:start_tools([],"app=vts"). -init_data(ConfigFiles,EvHandlers,LogDir,Tests) -> - call({init_data,ConfigFiles,EvHandlers,LogDir,Tests}). +init_data(ConfigFiles,EvHandlers,LogDir,LogOpts,Tests) -> + call({init_data,ConfigFiles,EvHandlers,LogDir,LogOpts,Tests}). stop() -> webtool:stop_tools([],"app=vts"), @@ -119,6 +120,8 @@ menu_frame(_Env,_Input) -> call(menu_frame). config_frame(_Env,_Input) -> call(config_frame). +browse_config_file(_Env,Input) -> + call({browse_config_file,Input}). add_config_file(_Env,Input) -> call({add_config_file,Input}). remove_config_file(_Env,Input) -> @@ -160,10 +163,11 @@ init(Parent) -> loop(State) -> receive - {{init_data,Config,EvHandlers,LogDir,Tests},From} -> + {{init_data,Config,EvHandlers,LogDir,LogOpts,Tests},From} -> %% ct:pal("State#state.current_log_dir=~p", [State#state.current_log_dir]), NewState = State#state{config=Config,event_handler=EvHandlers, - current_log_dir=LogDir,tests=Tests}, + current_log_dir=LogDir, + logopts=LogOpts,tests=Tests}, ct_install(NewState), return(From,ok), loop(NewState); @@ -182,6 +186,9 @@ loop(State) -> {config_frame,From} -> return(From,config_frame1(State)), loop(State); + {{browse_config_file,_Input},From} -> + return(From,ok), + loop(State); {{add_config_file,Input},From} -> {Return,State1} = add_config_file1(Input,State), ct_install(State1), @@ -241,10 +248,12 @@ loop(State) -> return(From,ok); {'EXIT',Pid,Reason} -> case State#state.test_runner of - Pid -> io:format("ERROR: test runner crashed: ~p\n",[Reason]); - _ -> ignore - end, - loop(State); + Pid -> + io:format("Test run error: ~p\n",[Reason]), + loop(State); + _ -> + loop(State) + end; {{test_info,_Type,_Data},From} -> return(From,ok), loop(State) @@ -270,10 +279,11 @@ return({To,Ref},Result) -> To ! {Ref, Result}. -run_test1(State=#state{tests=Tests,current_log_dir=LogDir}) -> +run_test1(State=#state{tests=Tests,current_log_dir=LogDir, + logopts=LogOpts}) -> Self=self(), RunTest = fun() -> - case ct_run:do_run(Tests,[],LogDir) of + case ct_run:do_run(Tests,[],LogDir,LogOpts) of {error,_Reason} -> aborted(); _ -> @@ -282,17 +292,18 @@ run_test1(State=#state{tests=Tests,current_log_dir=LogDir}) -> unlink(Self) end, Pid = spawn_link(RunTest), - Total = + {Total,Tests1} = receive {{test_info,start_info,{_,_,Cases}},From} -> return(From,ok), - Cases; + {Cases,Tests}; EXIT = {'EXIT',_,_} -> - self() ! EXIT + self() ! EXIT, + {0,[]} after 30000 -> - 0 + {0,[]} end, - State#state{test_runner=Pid,running=length(Tests), + State#state{test_runner=Pid,running=length(Tests1), total=Total,ok=0,fail=0,skip=0,testruns=[]}. @@ -356,22 +367,32 @@ config_frame1(State) -> config_body(State) -> Entry = [input("TYPE=file NAME=browse SIZE=40"), input("TYPE=hidden NAME=file")], + BrowseForm = + form( + "NAME=read_file_form METHOD=post ACTION=\"./browse_config_file\"", + table( + "BORDER=0", + [tr(td("1. Locate config file")), + tr(td(Entry))])), AddForm = form( - "NAME=read_file_form METHOD=post ACTION=\"./add_config_file\"", + "NAME=add_file_form METHOD=post ACTION=\"./add_config_file\"", table( "BORDER=0", - [tr( - [td(Entry), + [tr(td("2. Paste full config file name here")), + tr( + [td(input("TYPE=text NAME=file SIZE=40")), td("ALIGN=center", input("TYPE=submit onClick=\"file.value=browse.value;\"" " VALUE=\"Add\""))])])), + {Text,RemoveForm} = case State#state.config of [] -> - T = "To be able to run any tests, one or more configuration " - "files must be added. Enter the name of the configuration " - "file below and click the \"Add\" button.", + T = "Before running the tests, one or more configuration " + "files may be added. Locate the config file, copy its " + "full name, paste this into the text field below, then " + "click the \"Add\" button.", R = "", {T,R}; Files -> @@ -394,20 +415,24 @@ config_body(State) -> input("TYPE=submit VALUE=\"Remove\"")))])), {T,R} end, - + [h1("ALIGN=center","Config"), table( - "WIDTH=600 ALIGN=center CELLPADDING=5", + "WIDTH=450 ALIGN=center CELLPADDING=5", [tr(td(["BGCOLOR=",?INFO_BG_COLOR],Text)), - tr(td("ALIGN=center",AddForm)), - tr(td("ALIGN=center",RemoveForm))])]. - + tr(td("")), + tr(td("")), + tr(td("ALIGN=left",BrowseForm)), + tr(td("ALIGN=left",AddForm)), + tr(td("ALIGN=left",RemoveForm))])]. add_config_file1(Input,State) -> State1 = case get_input_data(Input,"file") of - "" -> State; - File -> State#state{config=[File|State#state.config]} + "" -> + State; + File -> + State#state{config=[File|State#state.config]} end, Return = config_frame1(State1), {Return,State1}. @@ -427,10 +452,17 @@ run_body(#state{running=Running}) when Running>0 -> [h1("ALIGN=center","Run Test"), p(["Test are ongoing: ",href("./result_frameset","Results")])]; run_body(State) -> - ConfigList = ul([li(File) || File <- State#state.config]), + ConfigList = + case State#state.config of + [] -> + ul(["none"]); + CfgFiles -> + ul([li(File) || File <- CfgFiles]) + end, ConfigFiles = [h3("Config Files"), ConfigList], - + {ok,CWD} = file:get_cwd(), + CurrWD = [h3("Current Working Directory"), ul(CWD)], AddDirForm = form( "NAME=add_dir_form METHOD=post ACTION=\"./add_test_dir\"", @@ -442,7 +474,6 @@ run_body(State) -> td("ALIGN=center", input("TYPE=submit onClick=\"dir.value=browse.value;\"" " VALUE=\"Add Test Dir\""))])])), - {LoadedTestsTable,Submit} = case create_testdir_entries(State#state.tests,1) of [] -> {"",""}; @@ -454,22 +485,20 @@ run_body(State) -> {table("CELLPADDING=5",[Heading,TestDirs]), submit_button()} end, - - %% It should be ok to have no config-file! Body = - %% case State#state.config of %% [] -> %% p("ALIGN=center", - %% href("./config_frame","Please select one or - %% more config files")); %% _ -> table( - "WIDTH=100%", - [tr(td(ConfigFiles)), + "WIDTH=450 ALIGN=center", + [tr(td("")), + tr(td("")), + tr(td(ConfigFiles)), + tr(td("")), + tr(td(CurrWD)), tr(td("")), tr(td(AddDirForm)), tr(td("")), tr(td(LoadedTestsTable)), - tr(td(Submit))]), - %% end, - + tr(td(Submit)) + ]), [h1("ALIGN=center","Run Test"), Body]. create_testdir_entries([{Dir,Suite,Case}|Tests],N) -> @@ -556,18 +585,17 @@ options([Element|Elements],Selected,N,Func) -> options([],_Selected,_N,_Func) -> []. -add_test_dir1(Input,State) -> +add_test_dir1(Input, State) -> State1 = case get_input_data(Input,"dir") of "" -> State; Dir0 -> Dir = case ct_util:is_test_dir(Dir0) of - true -> - Dir0; - false -> filename:join(Dir0,"test") + true -> Dir0; + false -> ct_util:get_testdir(Dir0, all) end, case filelib:is_dir(Dir) of - true -> + true -> Test = ct_run:tests(Dir), State#state{tests=State#state.tests++Test}; false -> @@ -577,8 +605,6 @@ add_test_dir1(Input,State) -> Return = run_frame1(State1), {Return,State1}. - - remove_test_dir1(Input,State) -> N = list_to_integer(get_input_data(Input,"dir")), State1 = State#state{tests=delete_test(N,State#state.tests)}, @@ -641,6 +667,9 @@ result_frameset2(State) -> "./redirect_to_result_log_frame"; {_Dir,0} -> filename:join(["/log_dir","index.html"]); + {_Dir,_} when State#state.testruns == [] -> + %% crash before first test + "./no_result_log_frame"; {_Dir,_} -> {_,CurrentLog} = hd(State#state.testruns), CurrentLog @@ -749,6 +778,8 @@ report1(tc_done,{_Suite,_Case,{skipped,_Reason}},State) -> State#state{skip=State#state.skip+1}; report1(tc_user_skip,{_Suite,_Case,_Reason},State) -> State#state{skip=State#state.skip+1}; +report1(tc_auto_skip,{_Suite,_Case,_Reason},State) -> + State#state{skip=State#state.skip+1}; report1(loginfo,_,State) -> State. @@ -850,6 +881,8 @@ h2(Text) -> ["<H2>",Text,"</H2>\n"]. h3(Text) -> ["<H3>",Text,"</H3>\n"]. +%%h4(Text) -> +%% ["<H4>",Text,"</H4>\n"]. font(Args,Text) -> ["<FONT ",Args,">\n",Text,"\n</FONT>\n"]. p(Text) -> diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index b7b099069c..284612b8f7 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -30,8 +30,11 @@ MODULES= \ ct_userconfig_callback \ ct_smoke_test_SUITE \ ct_event_handler_SUITE \ + ct_config_info_SUITE \ ct_groups_test_1_SUITE \ ct_groups_test_2_SUITE \ + ct_group_info_SUITE \ + ct_groups_spec_SUITE \ ct_sequence_1_SUITE \ ct_repeat_1_SUITE \ ct_testspec_1_SUITE \ diff --git a/lib/common_test/test/ct_config_SUITE.erl b/lib/common_test/test/ct_config_SUITE.erl index 8ce75f582a..18218bee47 100644 --- a/lib/common_test/test/ct_config_SUITE.erl +++ b/lib/common_test/test/ct_config_SUITE.erl @@ -228,7 +228,7 @@ expected_events(config_static_SUITE)-> {?eh,tc_start,{config_static_SUITE,test_config_name_already_in_use2}}, {?eh,tc_done, {config_static_SUITE,test_config_name_already_in_use2, - {skipped,{config_name_already_in_use,[x1,alias]}}}}, + {skipped,{config_name_already_in_use,[alias,x1]}}}}, {?eh,test_stats,{4,0,{2,0}}}, {?eh,tc_start,{config_static_SUITE,test_alias_tclocal}}, {?eh,tc_done,{config_static_SUITE,test_alias_tclocal,ok}}, diff --git a/lib/common_test/test/ct_config_info_SUITE.erl b/lib/common_test/test/ct_config_info_SUITE.erl new file mode 100644 index 0000000000..40da377ee5 --- /dev/null +++ b/lib/common_test/test/ct_config_info_SUITE.erl @@ -0,0 +1,178 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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: ct_config_info_SUITE +%%% +%%% Description: Test how Common Test handles info functions +%%% for the config functions. +%%% +%%%------------------------------------------------------------------- +-module(ct_config_info_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config1 = ct_test_support:init_per_suite(Config), + Config1. + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + ct_test_support:end_per_testcase(TestCase, Config). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + config_info + ]. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +config_info(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "config_info_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite}, + {label,config_info}], Config), + ok = execute(config_info, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +execute(Name, Opts, ERPid, Config) -> + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(Name, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(Name), + ct_test_support:verify_events(TestEvents, Events, Config). + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). + +%%%----------------------------------------------------------------- +%%% TEST EVENTS +%%%----------------------------------------------------------------- +events_to_check(Test) -> + %% 2 tests (ct:run_test + script_start) is default + events_to_check(Test, 2). + +events_to_check(_, 0) -> + []; +events_to_check(Test, N) -> + test_events(Test) ++ events_to_check(Test, N-1). + + +test_events(config_info) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,6}}, + {?eh,tc_done,{config_info_1_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{config_info_1_SUITE, + {init_per_group,unknown,[]}, + {failed,{timetrap_timeout,350}}}}, + {?eh,tc_auto_skip,{config_info_1_SUITE,t11, + {failed,{config_info_1_SUITE,init_per_group,{timetrap_timeout,350}}}}}, + {?eh,tc_auto_skip,{config_info_1_SUITE,end_per_group, + {failed,{config_info_1_SUITE,init_per_group, + {timetrap_timeout,350}}}}}], + + [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{config_info_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{config_info_1_SUITE,t21,ok}}, + {?eh,tc_start,{config_info_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{config_info_1_SUITE, + {end_per_group,unknown,[]}, + {failed,{timetrap_timeout,450}}}}], + [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{config_info_1_SUITE,{init_per_group,g3,[]},ok}}, + [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{config_info_1_SUITE, + {init_per_group,unknown,[]}, + {failed,{timetrap_timeout,400}}}}, + {?eh,tc_auto_skip,{config_info_1_SUITE,t41, + {failed,{config_info_1_SUITE,init_per_group, + {timetrap_timeout,400}}}}}, + {?eh,tc_auto_skip,{config_info_1_SUITE,end_per_group, + {failed,{config_info_1_SUITE,init_per_group, + {timetrap_timeout,400}}}}}], + {?eh,tc_start,{config_info_1_SUITE,t31}}, + {?eh,tc_done,{config_info_1_SUITE,t31, + {skipped,{failed,{config_info_1_SUITE,init_per_testcase, + {timetrap_timeout,250}}}}}}, + {?eh,tc_start,{config_info_1_SUITE,t32}}, + {?eh,tc_done,{config_info_1_SUITE,t32, + {failed,{config_info_1_SUITE,end_per_testcase, + {timetrap_timeout,250}}}}}, + + [{?eh,tc_start,{config_info_1_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{config_info_1_SUITE,{init_per_group,g5,[]},ok}}, + {?eh,tc_done,{config_info_1_SUITE,t51,ok}}, + {?eh,tc_start,{config_info_1_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{config_info_1_SUITE, + {end_per_group,unknown,[]}, + {failed,{timetrap_timeout,400}}}}], + {?eh,tc_start,{config_info_1_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{config_info_1_SUITE,{end_per_group,g3,[]},ok}}], + + {?eh,tc_start,{config_info_1_SUITE,end_per_suite}}, + {?eh,tc_done,{config_info_1_SUITE,end_per_suite, + {failed,{timetrap_timeout,300}}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]. diff --git a/lib/common_test/test/ct_config_info_SUITE_data/config_info_1_SUITE.erl b/lib/common_test/test/ct_config_info_SUITE_data/config_info_1_SUITE.erl new file mode 100644 index 0000000000..53a233b7a4 --- /dev/null +++ b/lib/common_test/test/ct_config_info_SUITE_data/config_info_1_SUITE.erl @@ -0,0 +1,168 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(config_info_1_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +%%%----------------------------------------------------------------- + +suite() -> + [{timetrap,500}]. + +%%%----------------------------------------------------------------- + +group(_) -> + [{timetrap,250}]. + +%%%----------------------------------------------------------------- + +init_per_suite() -> + ct:pal("init_per_suite info called", []), + [{timetrap,1000}, + {require,suite_data}, + {default_config,suite_data,suite_data_val}]. + +init_per_suite(Config) -> + suite_data_val = ct:get_config(suite_data), + ct:sleep(750), + Config. + +%%%----------------------------------------------------------------- + +end_per_suite() -> + ct:pal("end_per_suite info called", []), + [{timetrap,300}, + {require,suite_data2}, + {default_config,suite_data2,suite_data2_val}]. + +end_per_suite(_Config) -> + suite_data2_val = ct:get_config(suite_data2), + ct:sleep(500), + ok. + +%%%----------------------------------------------------------------- + +init_per_group(g1) -> + ct:pal("init_per_group(g1) info called", []), + [{timetrap,350}]; +init_per_group(G) -> + ct:pal("init_per_group(~w) info called", [G]), + [{timetrap,400}]. + +init_per_group(g1, _Config) -> + ct:sleep(1000); +init_per_group(g4, _Config) -> + ct:sleep(1000); +init_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = proplists:delete(name, GrProps), + ct:comment(io_lib:format("init( ~w ): ~p", [G, GrProps1])), + ct:pal("init( ~w ): ~p", [G, GrProps1]), + Config. + +%%%----------------------------------------------------------------- + +end_per_group(g2) -> + ct:pal("end_per_group(g2) info called", []), + [{timetrap,450}]; +end_per_group(G) -> + ct:pal("end_per_group(~w) info called", [G]), + [{timetrap,400}]. + +end_per_group(g2, _Config) -> + ct:sleep(1000); +end_per_group(g5, _Config) -> + ct:sleep(1000); +end_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = proplists:delete(name, GrProps), + ct:comment(io_lib:format("end( ~w ): ~p", [G, GrProps1])), + ct:pal("end( ~w ): ~p", [G, GrProps1]), + ok. + +%%%----------------------------------------------------------------- +init_per_testcase() -> + [{timetrap,750}]. + +init_per_testcase(t1, _Config) -> + ct:sleep(1000); +init_per_testcase(t31, _Config) -> + ct:sleep(1000); +init_per_testcase(_TestCase, Config) -> + Config. + +%%%----------------------------------------------------------------- + +end_per_testcase() -> + [{timetrap,600}]. + +end_per_testcase(t2, _Config) -> + ct:sleep(1000); +end_per_testcase(t32, _Config) -> + ct:sleep(1000); +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% TEST DECLARATIONS +%%-------------------------------------------------------------------- + +groups() -> + [ + {g1,[],[t11]}, + {g2,[],[t21]}, + {g3,[],[{g4,[],[t41]}, t31, t32, {g5,[],[t51]}]} + ]. + +all() -> + [ + {group,g1}, + {group,g2}, + {group,g3} + ]. + +%%----------------------------------------------------------------- +%% TEST CASES +%%----------------------------------------------------------------- + +t1(_) -> + exit(should_not_execute). + +t2(_) -> + ok. + +t11(_) -> + exit(should_not_execute). + +t21(_) -> + ok. + +t31(_) -> + exit(should_not_execute). + +t32(_) -> + ok. + +t41(_) -> + exit(should_not_execute). + +t51(_) -> + ok. diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl index 6867e59b60..2b3157ff3b 100644 --- a/lib/common_test/test/ct_error_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE.erl @@ -60,7 +60,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [cfg_error, lib_error, no_compile, timetrap_end_conf, - timetrap_normal, timetrap_extended]. + timetrap_normal, timetrap_extended, timetrap_parallel, + timetrap_fun]. groups() -> []. @@ -228,6 +229,28 @@ timetrap_parallel(Config) when is_list(Config) -> ok = ct_test_support:verify_events(TestEvents, Events, Config). %%%----------------------------------------------------------------- +%%% +timetrap_fun(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Join = fun(D, S) -> filename:join(D, "error/test/"++S) end, + Suites = [Join(DataDir, "timetrap_4_SUITE"), + Join(DataDir, "timetrap_5_SUITE"), + Join(DataDir, "timetrap_6_SUITE"), + Join(DataDir, "timetrap_7_SUITE")], + {Opts,ERPid} = setup([{suite,Suites}], Config), + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(timetrap_fun, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(timetrap_fun), + ok = ct_test_support:verify_events(TestEvents, Events, Config). + + +%%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -260,7 +283,7 @@ test_events(cfg_error) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,start_info,{14,14,43}}, + {?eh,start_info,{14,14,45}}, {?eh,tc_start,{cfg_error_1_SUITE,init_per_suite}}, {?eh,tc_done, @@ -280,41 +303,21 @@ test_events(cfg_error) -> {?eh,tc_start,{cfg_error_2_SUITE,init_per_suite}}, {?eh,tc_done, {cfg_error_2_SUITE,init_per_suite, - {failed,{error,{{badmatch,[1,2]}, - [{cfg_error_2_SUITE,init_per_suite,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {failed,{error,{{badmatch,[1,2]},'_'}}}}}, {?eh,tc_auto_skip, {cfg_error_2_SUITE,tc1, {failed,{cfg_error_2_SUITE,init_per_suite, - {'EXIT',{{badmatch,[1,2]}, - [{cfg_error_2_SUITE,init_per_suite,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {'EXIT',{{badmatch,[1,2]},'_'}}}}}}, {?eh,test_stats,{0,0,{0,3}}}, {?eh,tc_auto_skip, {cfg_error_2_SUITE,tc2, {failed,{cfg_error_2_SUITE,init_per_suite, - {'EXIT',{{badmatch,[1,2]}, - [{cfg_error_2_SUITE,init_per_suite,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {'EXIT',{{badmatch,[1,2]},'_'}}}}}}, {?eh,test_stats,{0,0,{0,4}}}, {?eh,tc_auto_skip, {cfg_error_2_SUITE,end_per_suite, {failed,{cfg_error_2_SUITE,init_per_suite, - {'EXIT',{{badmatch,[1,2]}, - [{cfg_error_2_SUITE,init_per_suite,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {'EXIT',{{badmatch,[1,2]},'_'}}}}}}, {?eh,tc_start,{cfg_error_3_SUITE,init_per_suite}}, {?eh,tc_done, @@ -373,12 +376,7 @@ test_events(cfg_error) -> {?eh,tc_done,{cfg_error_6_SUITE,{end_per_group,g1,[]},ok}}], {?eh,tc_start,{cfg_error_6_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_6_SUITE,end_per_suite, - {failed,{error,{{badmatch,[1,2]}, - [{cfg_error_6_SUITE,end_per_suite,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {failed,{error,{{badmatch,[1,2]},'_'}}}}}, {?eh,tc_start,{cfg_error_7_SUITE,init_per_suite}}, {?eh,tc_done,{cfg_error_7_SUITE,init_per_suite,ok}}, @@ -427,31 +425,16 @@ test_events(cfg_error) -> [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g3,[]}}}, {?eh,tc_done, {cfg_error_8_SUITE,{init_per_group,g3,[]}, - {failed,{error,{{badmatch,42}, - [{cfg_error_8_SUITE,init_per_group,2}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {failed,{error,{{badmatch,42},'_'}}}}}, {?eh,tc_auto_skip, {cfg_error_8_SUITE,tc1, {failed,{cfg_error_8_SUITE,init_per_group, - {'EXIT',{{badmatch,42}, - [{cfg_error_8_SUITE,init_per_group,2}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {'EXIT',{{badmatch,42},'_'}}}}}}, {?eh,test_stats,{4,0,{0,13}}}, {?eh,tc_auto_skip, {cfg_error_8_SUITE,end_per_group, {failed,{cfg_error_8_SUITE,init_per_group, - {'EXIT',{{badmatch,42}, - [{cfg_error_8_SUITE,init_per_group,2}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}], + {'EXIT',{{badmatch,42},'_'}}}}}}], [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g4,[]}}}, {?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g4,[]},ok}}, @@ -510,7 +493,7 @@ test_events(cfg_error) -> {?eh,tc_start,{cfg_error_9_SUITE,tc1}}, {?eh,tc_done,{cfg_error_9_SUITE,tc1, {skipped,{failed,{cfg_error_9_SUITE,init_per_testcase, - tc1_should_be_skipped}}}}}, + {tc1_should_be_skipped,'_'}}}}}}, {?eh,test_stats,{9,0,{0,15}}}, {?eh,tc_start,{cfg_error_9_SUITE,tc2}}, {?eh,tc_done,{cfg_error_9_SUITE,tc2, @@ -520,12 +503,7 @@ test_events(cfg_error) -> {?eh,tc_start,{cfg_error_9_SUITE,tc3}}, {?eh,tc_done,{cfg_error_9_SUITE,tc3, {skipped,{failed,{cfg_error_9_SUITE,init_per_testcase, - {{badmatch,undefined}, - [{cfg_error_9_SUITE,init_per_testcase,2}, - {test_server,my_apply,3}, - {test_server,init_per_testcase,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {{badmatch,undefined},'_'}}}}}}, {?eh,test_stats,{9,0,{0,17}}}, {?eh,tc_start,{cfg_error_9_SUITE,tc4}}, {?eh,tc_done, @@ -557,18 +535,18 @@ test_events(cfg_error) -> {?eh,tc_start,{cfg_error_9_SUITE,tc13}}, {?eh,tc_done,{cfg_error_9_SUITE,tc13, {failed,{cfg_error_9_SUITE,end_per_testcase, - {'EXIT',{{badmatch,undefined}, - [{cfg_error_9_SUITE,end_per_testcase,2}, - {test_server,my_apply,3}, - {test_server,do_end_per_testcase,4}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {'EXIT',{{badmatch,undefined},'_'}}}}}}, {?eh,test_stats,{12,3,{0,18}}}, {?eh,tc_start,{cfg_error_9_SUITE,tc14}}, {?eh,tc_done, {cfg_error_9_SUITE,tc14,{failed,{error,tc14_should_be_failed}}}}, - {?eh,test_stats,{12,4,{0,18}}}, - + {?eh,tc_start,{cfg_error_9_SUITE,tc15}}, + {?eh,tc_done, + {cfg_error_9_SUITE,tc15,{failed,{error,this_error_must_show}}}}, + {?eh,tc_start,{cfg_error_9_SUITE,tc16}}, + {?eh,tc_done, + {cfg_error_9_SUITE,tc16,{failed,{error,this_error_must_show}}}}, + {?eh,test_stats,{12,6,{0,18}}}, {?eh,tc_start,{cfg_error_9_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_9_SUITE,end_per_suite,ok}}, @@ -578,49 +556,49 @@ test_events(cfg_error) -> {?eh,tc_auto_skip,{cfg_error_10_SUITE,tc1, {failed,{cfg_error_10_SUITE,init_per_suite, {failed,fail_init_per_suite}}}}}, - {?eh,test_stats,{12,4,{0,19}}}, + {?eh,test_stats,{12,6,{0,19}}}, {?eh,tc_auto_skip,{cfg_error_10_SUITE,end_per_suite, {failed,{cfg_error_10_SUITE,init_per_suite, {failed,fail_init_per_suite}}}}}, {?eh,tc_start,{cfg_error_11_SUITE,init_per_suite}}, {?eh,tc_done,{cfg_error_11_SUITE,init_per_suite,ok}}, {?eh,tc_start,{cfg_error_11_SUITE,tc1}}, - {?eh,tc_done,{cfg_error_11_SUITE,tc1, - {skipped,{config_name_already_in_use,[dummy0]}}}}, - {?eh,test_stats,{12,4,{1,19}}}, + {?eh,tc_done, {cfg_error_11_SUITE,tc1, + {skipped,{config_name_already_in_use,[dummy_alias]}}}}, + {?eh,test_stats,{12,6,{1,19}}}, {?eh,tc_start,{cfg_error_11_SUITE,tc2}}, {?eh,tc_done,{cfg_error_11_SUITE,tc2,ok}}, - {?eh,test_stats,{13,4,{1,19}}}, + {?eh,test_stats,{13,6,{1,19}}}, {?eh,tc_start,{cfg_error_11_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_11_SUITE,end_per_suite,ok}}, {?eh,tc_start,{cfg_error_12_SUITE,tc1}}, - {?eh,tc_done,{cfg_error_12_SUITE,tc1,{failed,{timetrap_timeout,500}}}}, - {?eh,test_stats,{13,5,{1,19}}}, + {?eh,tc_done,{ct_framework,init_tc,{framework_error,{timetrap,500}}}}, + {?eh,test_stats,{13,7,{1,19}}}, {?eh,tc_start,{cfg_error_12_SUITE,tc2}}, {?eh,tc_done,{cfg_error_12_SUITE,tc2,{failed, {cfg_error_12_SUITE,end_per_testcase, {timetrap_timeout,500}}}}}, - {?eh,test_stats,{14,5,{1,19}}}, + {?eh,test_stats,{14,7,{1,19}}}, {?eh,tc_start,{cfg_error_12_SUITE,tc3}}, {?eh,tc_done,{cfg_error_12_SUITE,tc3,ok}}, - {?eh,test_stats,{15,5,{1,19}}}, + {?eh,test_stats,{15,7,{1,19}}}, {?eh,tc_start,{cfg_error_12_SUITE,tc4}}, {?eh,tc_done,{cfg_error_12_SUITE,tc4,{failed, {cfg_error_12_SUITE,end_per_testcase, {timetrap_timeout,500}}}}}, - {?eh,test_stats,{16,5,{1,19}}}, + {?eh,test_stats,{16,7,{1,19}}}, {?eh,tc_start,{cfg_error_13_SUITE,init_per_suite}}, {?eh,tc_done,{cfg_error_13_SUITE,init_per_suite,ok}}, {?eh,tc_start,{cfg_error_13_SUITE,tc1}}, {?eh,tc_done,{cfg_error_13_SUITE,tc1,ok}}, - {?eh,test_stats,{17,5,{1,19}}}, + {?eh,test_stats,{17,7,{1,19}}}, {?eh,tc_start,{cfg_error_13_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_13_SUITE,end_per_suite,ok}}, {?eh,tc_start,{cfg_error_14_SUITE,init_per_suite}}, {?eh,tc_done,{cfg_error_14_SUITE,init_per_suite,ok}}, {?eh,tc_start,{cfg_error_14_SUITE,tc1}}, {?eh,tc_done,{cfg_error_14_SUITE,tc1,ok}}, - {?eh,test_stats,{18,5,{1,19}}}, + {?eh,test_stats,{18,7,{1,19}}}, {?eh,tc_start,{cfg_error_14_SUITE,end_per_suite}}, {?eh,tc_done,{cfg_error_14_SUITE,end_per_suite, {comment, @@ -640,13 +618,7 @@ test_events(lib_error) -> {?eh,tc_done, {lib_error_1_SUITE,lines_error,{failed, {error, - {{badmatch,[1,2]}, - [{lib_lines,do_error,0}, - {lib_error_1_SUITE,lines_error,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {{badmatch,[1,2]},'_'}}}}}, {?eh,test_stats,{0,1,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,lines_exit}}, {?eh,tc_done, @@ -654,7 +626,7 @@ test_events(lib_error) -> {?eh,test_stats,{0,2,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,lines_hang}}, {?eh,tc_done, - {lib_lines,do_hang,{failed,{timetrap_timeout,3000}}}}, + {lib_error_1_SUITE,lines_hang,{failed,{timetrap_timeout,3000}}}}, {?eh,test_stats,{0,3,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,lines_throw}}, {?eh,tc_done, @@ -665,13 +637,7 @@ test_events(lib_error) -> {?eh,tc_done, {lib_error_1_SUITE,no_lines_error,{failed, {error, - {{badmatch,[1,2]}, - [{lib_no_lines,do_error,0}, - {lib_error_1_SUITE,no_lines_error,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {{badmatch,[1,2]},'_'}}}}}, {?eh,test_stats,{0,5,{0,0}}}, {?eh,tc_start,{lib_error_1_SUITE,no_lines_exit}}, {?eh,tc_done, @@ -809,7 +775,7 @@ test_events(timetrap_parallel) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,start_info,{1,1,7}}, + {?eh,start_info,{1,1,8}}, {?eh,tc_done,{timetrap_3_SUITE,init_per_suite,ok}}, {parallel, [{?eh,tc_start, @@ -821,9 +787,12 @@ test_events(timetrap_parallel) -> {?eh,tc_start,{timetrap_3_SUITE,tc2}}, {?eh,tc_start,{timetrap_3_SUITE,tc3}}, {?eh,tc_start,{timetrap_3_SUITE,tc4}}, + {?eh,tc_start,{timetrap_3_SUITE,tc5}}, {?eh,tc_start,{timetrap_3_SUITE,tc6}}, {?eh,tc_start,{timetrap_3_SUITE,tc7}}, {?eh,tc_done, + {timetrap_3_SUITE,tc5,ok}}, + {?eh,tc_done, {timetrap_3_SUITE,tc1,{failed,{timetrap_timeout,500}}}}, {?eh,tc_done, {timetrap_3_SUITE,tc2,{failed,{timetrap_timeout,1000}}}}, @@ -837,11 +806,90 @@ test_events(timetrap_parallel) -> {timetrap_3_SUITE,tc4,{failed,{timetrap_timeout,2000}}}}, {?eh,tc_done, {timetrap_3_SUITE,tc3,{failed,{timetrap_timeout,3000}}}}, - {?eh,test_stats,{0,7,{0,0}}}, + {?eh,test_stats,{1,7,{0,0}}}, {?eh,tc_start, {timetrap_3_SUITE,{end_per_group,g1,[parallel]}}}, {?eh,tc_done, {timetrap_3_SUITE,{end_per_group,g1,[parallel]},ok}}]}, {?eh,tc_done,{timetrap_3_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, - {?eh,stop_logging,[]}]. + {?eh,stop_logging,[]}]; + +test_events(timetrap_fun) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,start_info,{4,4,17}}, + {?eh,tc_done,{timetrap_4_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{timetrap_4_SUITE,tc0}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc0,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_4_SUITE,tc1}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc1,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{timetrap_4_SUITE,tc2}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc2,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{timetrap_4_SUITE,tc3}}, + {?eh,tc_done, + {timetrap_4_SUITE,tc3,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,4,{0,0}}}, + {?eh,tc_done,{timetrap_4_SUITE,end_per_suite,ok}}, + + {?eh,tc_done,{timetrap_5_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{timetrap_5_SUITE,tc0}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc0,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,5,{0,0}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc1}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc1,{skipped,{timetrap_error,kaboom}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc2}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc2,{skipped,{timetrap_error,kaboom}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc3}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc3, + {skipped,{invalid_time_format,{timetrap_utils,timetrap_val,[5000]}}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc4}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc4,{skipped,{invalid_time_format,'_'}}}}, + {?eh,test_stats,{0,5,{0,4}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc5}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc5,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc6}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc6,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_5_SUITE,tc7}}, + {?eh,tc_done, + {timetrap_5_SUITE,tc7,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,8,{0,4}}}, + {?eh,tc_done,{timetrap_5_SUITE,end_per_suite,ok}}, + + {?eh,tc_start,{timetrap_6_SUITE,init_per_suite}}, + {?eh,tc_done, + {timetrap_6_SUITE,init_per_suite,{skipped,{timetrap_error,kaboom}}}}, + {?eh,tc_auto_skip, + {timetrap_6_SUITE,tc0,{timetrap_error,kaboom}}}, + {?eh,test_stats,{0,8,{0,5}}}, + {?eh,tc_auto_skip, + {timetrap_6_SUITE,end_per_suite,{timetrap_error,kaboom}}}, + + {?eh,tc_done,{timetrap_7_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{timetrap_7_SUITE,tc0}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc0,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{timetrap_7_SUITE,tc1}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc1,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{timetrap_7_SUITE,tc2}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc2,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{timetrap_7_SUITE,tc3}}, + {?eh,tc_done, + {timetrap_7_SUITE,tc3,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,12,{0,5}}}, + {?eh,tc_done,{timetrap_7_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl index ce94533110..879561ebb9 100644 --- a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_11_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2011. 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 @@ -29,10 +29,7 @@ suite() -> [{timetrap,{seconds,2}}, {require, dummy0}, {default_config, dummy0, "suite/0"}, - {require, dummy1}, {default_config, dummy1, "suite/0"}, - {require, dummy2}, {default_config, dummy2, "suite/0"}]. - - + {require, dummy_alias, dummy1}, {default_config, dummy1, "suite/0"}]. %%-------------------------------------------------------------------- %% Function: init_per_suite(Config0) -> @@ -119,16 +116,17 @@ groups() -> %% Reason = term() %%-------------------------------------------------------------------- all() -> - [tc1, tc2]. + [tc1,tc2]. tc1() -> - [{require, dummy0}, {default_config, dummy0, "tc1"}]. + [{require, dummy0}, {default_config, dummy0, "tc1"}, + {require, dummy_alias, dummy2}, {default_config, dummy2, "tc1"}]. tc1(_) -> dummy. tc2() -> - [{timetrap,1}]. + [{timetrap,10}]. tc2(_) -> dummy. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl index c4e0d72948..f292985c0c 100644 --- a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl @@ -76,7 +76,7 @@ init_per_testcase(tc1, Config) -> Config; init_per_testcase(tc2, Config) -> ct:comment("init_per_testcase(tc2) timeout"), - timer:sleep(5000), + ct:sleep(5000), Config; init_per_testcase(tc3, Config) -> badmatch = ?config(void, Config), @@ -96,22 +96,20 @@ init_per_testcase(_, Config) -> %%-------------------------------------------------------------------- end_per_testcase(tc11, _Config) -> ct:comment("A warning should be printed"), - exit(warning_should_be_printed), - done; + exit(warning_should_be_printed); end_per_testcase(tc12, _Config) -> ct:comment("A warning should be printed"), - timer:sleep(5000), - done; + ct:sleep(5000); end_per_testcase(tc13, Config) -> ct:comment("A warning should be printed"), - badmatch = ?config(void, Config), - done; + badmatch = ?config(void, Config); end_per_testcase(tc14, Config) -> ok = ?config(tc_status, Config), {fail,tc14_should_be_failed}; end_per_testcase(tc15, Config) -> - {failed,byebye} = ?config(tc_status, Config), - ok; + exit(kaboom); +end_per_testcase(tc16, Config) -> + ct:sleep(5000); end_per_testcase(_TestCase, _Config) -> done. @@ -139,7 +137,7 @@ groups() -> %%-------------------------------------------------------------------- all() -> [tc1,tc2,tc3,tc4,tc5,tc6,tc7, - tc11,tc12,tc13,tc14]. + tc11,tc12,tc13,tc14,tc15,tc16]. tc1(_) -> fini. @@ -189,4 +187,6 @@ tc14(_) -> ct:comment("This one should be failed by eptc"), yes. tc15(_) -> - exit(byebye). + exit(this_error_must_show). +tc16(_) -> + exit(this_error_must_show). diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl new file mode 100644 index 0000000000..8271b23afe --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl @@ -0,0 +1,146 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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(timetrap_3_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 3). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{seconds,?TO}}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + [{g1,[parallel],[tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7]}]. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [{group,g1}]. + +tc0() -> + [{timetrap,2000}]. +tc0(_) -> + ct:comment("TO after 2 sec"), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,500}]. +tc1(_) -> + ct:comment("TO after 1/2 sec"), + ct:sleep({seconds,5}), + ok. + +tc2() -> + [{timetrap,1000}]. +tc2(_) -> + ct:comment("TO after 1 sec"), + ct:sleep({seconds,5}), + ok. + +tc3(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. + +tc4() -> + [{timetrap,2000}]. +tc4(_) -> + ct:comment(io_lib:format("TO after 2 sec", [])), + ct:sleep({seconds,5}), + ok. + +tc5() -> + [{timetrap,2000}]. +tc5(_) -> + ct:comment("No timeout"), + ct:sleep({seconds,1}), + ok. + +tc6() -> + [{timetrap,1000}]. +tc6(_) -> + ct:comment("TO after 1 sec"), + ct:sleep({seconds,5}), + ok. + +tc7() -> + [{timetrap,1500}]. +tc7(_) -> + ct:comment("TO after 1 1/2 sec"), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl new file mode 100644 index 0000000000..d902454f09 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl @@ -0,0 +1,135 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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(timetrap_4_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{timetrap_utils,timetrap_val,[{seconds,?TO}]}}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0,tc1,tc2,tc3]. + +tc0(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,{timetrap_utils,timetrap_val,[2000]}}]. +tc1(_) -> + ct:comment("TO after 2 sec"), + ct:sleep({seconds,5}), + ok. + +tc2() -> + [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}]. +tc2(_) -> + ct:comment("TO after 0.5 sec"), + ct:sleep(1000), + ok. + +tc3(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl new file mode 100644 index 0000000000..c5d4b5062e --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl @@ -0,0 +1,155 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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(timetrap_5_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap, fun() -> timetrap_utils:timetrap_val({seconds,?TO}) end}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7]. + +tc0(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,{timetrap_utils,timetrap_exit,[kaboom]}}]. +tc1(_) -> + exit(this_should_not_execute). + +tc2() -> + [{timetrap,fun() -> exit(kaboom) end}]. +tc2(_) -> + exit(this_should_not_execute). + +tc3() -> + [{timetrap,{timetrap_utils,timetrap_err_mfa,[]}}]. +tc3(_) -> + exit(this_should_not_execute). + +tc4() -> + [{timetrap,fun() -> timetrap_utils:timetrap_err_fun() end}]. +tc4(_) -> + exit(this_should_not_execute). + +tc5() -> + [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,40}, + {seconds,1}]}}]. +tc5(_) -> + ct:comment("TO after 40+1 sec"), + ct:sleep({seconds,42}), + ok. + +tc6() -> + [{timetrap,fun() -> ct:sleep(6000), 1000 end}]. +tc6(_) -> + ct:comment("TO after 6+1 sec"), + ct:sleep({seconds,10}). + +tc7(_) -> + ct:comment(io_lib:format("TO after ~w sec", [?TO])), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl new file mode 100644 index 0000000000..90467ff752 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl @@ -0,0 +1,114 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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(timetrap_6_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap, fun() -> exit(kaboom) end}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0]. + +tc0(_) -> + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl new file mode 100644 index 0000000000..b25b7770a7 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl @@ -0,0 +1,137 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. 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(timetrap_7_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +-define(TO, 1). +-define(HANG, 6). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,?HANG}, + {seconds,?TO}]}}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [tc0,tc1,tc2,tc3]. + +tc0(_) -> + ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])), + ct:sleep({seconds,5}), + ok. + +tc1() -> + [{timetrap,{timetrap_utils,timetrap_val,[2000]}}]. +tc1(_) -> + ct:comment("TO after 2 sec"), + ct:sleep({seconds,5}), + ok. + +tc2() -> + [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}]. +tc2(_) -> + ct:comment("TO after 0.5 sec"), + ct:sleep(1000), + ok. + +tc3(_) -> + ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])), + ct:sleep({seconds,5}), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl new file mode 100644 index 0000000000..fcde6cd701 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl @@ -0,0 +1,43 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(timetrap_utils). + +-export([timetrap_val/1, + timetrap_err_fun/0, + timetrap_err_mfa/0, + timetrap_exit/1, + timetrap_timeout/2]). + +timetrap_val(Val) -> + Val. + +timetrap_err_fun() -> + fun() -> 5000 end. + +timetrap_err_mfa() -> + {?MODULE,timetrap_val,[5000]}. + +timetrap_exit(Reason) -> + exit(Reason). + +timetrap_timeout(Sleep, Val) -> + ct:sleep(Sleep), + Val. + diff --git a/lib/common_test/test/ct_group_info_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE.erl new file mode 100644 index 0000000000..2da8219196 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE.erl @@ -0,0 +1,859 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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: ct_group_info_SUITE +%%% +%%% Description: +%%% Test that the group info function works as expected with regards +%%% to timetraps and require (and default config values). +%%% +%%%------------------------------------------------------------------- +-module(ct_group_info_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config1 = ct_test_support:init_per_suite(Config), + Config1. + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + ct_test_support:end_per_testcase(TestCase, Config). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + timetrap_all, + timetrap_group, + timetrap_group_case, + timetrap_all_no_ips, + timetrap_all_no_ipg, + require, + require_default, + require_no_ips, + require_no_ipg + ]. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +timetrap_all(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_timetrap_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite}, + {label,timetrap_all}], Config), + ok = execute(timetrap_all, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +timetrap_group(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_timetrap_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{group,[g1,g3,g7]}, + {label,timetrap_group}], Config), + ok = execute(timetrap_group, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +timetrap_group_case(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_timetrap_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{group,g4},{testcase,t41}, + {label,timetrap_group_case}], Config), + ok = execute(timetrap_group_case, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +timetrap_all_no_ips(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_timetrap_2_SUITE"), + {Opts,ERPid} = setup([{suite,Suite}, + {label,timetrap_all_no_ips}], Config), + ok = execute(timetrap_all_no_ips, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +timetrap_all_no_ipg(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_timetrap_3_SUITE"), + {Opts,ERPid} = setup([{suite,Suite}, + {label,timetrap_all_no_ipg}], Config), + ok = execute(timetrap_all_no_ipg, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +require(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_require_1_SUITE"), + CfgFile = filename:join(DataDir, "vars.cfg"), + {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile}, + {label,require}], Config), + ok = execute(require, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +require_default(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_require_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite}, + {label,require_default}], Config), + ok = execute(require_default, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +require_no_ips(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_require_2_SUITE"), + CfgFile = filename:join(DataDir, "vars.cfg"), + {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile}, + {label,require_no_ips}], Config), + ok = execute(require_no_ips, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +require_no_ipg(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "group_require_3_SUITE"), + CfgFile = filename:join(DataDir, "vars.cfg"), + {Opts,ERPid} = setup([{suite,Suite},{config,CfgFile}, + {label,require_no_ipg}], Config), + ok = execute(require_no_ipg, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +execute(Name, Opts, ERPid, Config) -> + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(Name, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(Name), + ct_test_support:verify_events(TestEvents, Events, Config). + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). + +%%%----------------------------------------------------------------- +%%% TEST EVENTS +%%%----------------------------------------------------------------- +events_to_check(Test) -> + %% 2 tests (ct:run_test + script_start) is default + events_to_check(Test, 2). + +events_to_check(_, 0) -> + []; +events_to_check(Test, N) -> + test_events(Test) ++ events_to_check(Test, N-1). + + +test_events(timetrap_all) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,14}}, + {?eh,tc_done,{group_timetrap_1_SUITE,init_per_suite,ok}}, + + {?eh,tc_done,{group_timetrap_1_SUITE,t1,{failed,{timetrap_timeout,1000}}}}, + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t11,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g1,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t21,{failed,{timetrap_timeout,1500}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g2,[]},ok}}], + + {?eh,tc_done,{group_timetrap_1_SUITE,t2,{failed,{timetrap_timeout,1000}}}}, + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g3,[]},ok}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g4,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t41,{failed,{timetrap_timeout,250}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g4,[]},ok}}], + {?eh,tc_done,{group_timetrap_1_SUITE,t31,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g5,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t51,{failed,{timetrap_timeout,1500}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g5,[]},ok}}], + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g3,[]},ok}}], + + {?eh,tc_done,{group_timetrap_1_SUITE,t3,{failed,{timetrap_timeout,250}}}}, + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g6,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g6,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t61,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g6,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g6,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g7,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g7,[]},ok}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g8,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g8,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t81,{failed,{timetrap_timeout,750}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g8,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g8,[]},ok}}], + {?eh,tc_done,{group_timetrap_1_SUITE,t71,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g9,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g9,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t91,{failed,{timetrap_timeout,250}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g9,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g9,[]},ok}}], + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g7,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g7,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g10,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g10,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t101,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g10,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g10,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g11,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g11,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t111,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,14,{0,0}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g11,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g11,[]},ok}}], + + {?eh,tc_done,{group_timetrap_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(timetrap_group) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,7}}, + {?eh,tc_done,{group_timetrap_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t11,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g1,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g3,[]},ok}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g4,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t41,{failed,{timetrap_timeout,250}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g4,[]},ok}}], + {?eh,tc_done,{group_timetrap_1_SUITE,t31,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g5,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t51,{failed,{timetrap_timeout,1500}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g5,[]},ok}}], + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g3,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g7,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g7,[]},ok}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g8,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g8,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t81,{failed,{timetrap_timeout,750}}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g8,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g8,[]},ok}}], + {?eh,tc_done,{group_timetrap_1_SUITE,t71,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g9,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g9,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t91,{failed,{timetrap_timeout,250}}}}, + {?eh,test_stats,{0,7,{0,0}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g9,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g9,[]},ok}}], + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g7,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g7,[]},ok}}], + + {?eh,tc_done,{group_timetrap_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(timetrap_group_case) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,1}}, + {?eh,tc_done,{group_timetrap_1_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g3,[]},ok}}, + [{?eh,tc_start,{group_timetrap_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{init_per_group,g4,[]},ok}}, + {?eh,tc_done,{group_timetrap_1_SUITE,t41,{failed,{timetrap_timeout,250}}}}, + {?eh,test_stats,{0,1,{0,0}}}, + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g4,[]},ok}}], + {?eh,tc_start,{group_timetrap_1_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_1_SUITE,{end_per_group,g3,[]},ok}}], + + {?eh,tc_done,{group_timetrap_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(timetrap_all_no_ips) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,14}}, + + {?eh,tc_done,{group_timetrap_2_SUITE,t1,{failed,{timetrap_timeout,1000}}}}, + + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t11,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g1,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t21,{failed,{timetrap_timeout,1500}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g2,[]},ok}}], + + {?eh,tc_done,{group_timetrap_2_SUITE,t2,{failed,{timetrap_timeout,1000}}}}, + + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g3,[]},ok}}, + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g4,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t41,{failed,{timetrap_timeout,250}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g4,[]},ok}}], + {?eh,tc_done,{group_timetrap_2_SUITE,t31,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g5,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t51,{failed,{timetrap_timeout,1500}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g5,[]},ok}}], + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g3,[]},ok}}], + + {?eh,tc_done,{group_timetrap_2_SUITE,t3,{failed,{timetrap_timeout,250}}}}, + + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g6,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g6,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t61,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g6,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g6,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g7,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g7,[]},ok}}, + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g8,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g8,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t81,{failed,{timetrap_timeout,750}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g8,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g8,[]},ok}}], + {?eh,tc_done,{group_timetrap_2_SUITE,t71,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g9,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g9,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t91,{failed,{timetrap_timeout,250}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g9,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g9,[]},ok}}], + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g7,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g7,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g10,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g10,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t101,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g10,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g10,[]},ok}}], + + [{?eh,tc_start,{group_timetrap_2_SUITE,{init_per_group,g11,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{init_per_group,g11,[]},ok}}, + {?eh,tc_done,{group_timetrap_2_SUITE,t111,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,14,{0,0}}}, + {?eh,tc_start,{group_timetrap_2_SUITE,{end_per_group,g11,[]}}}, + {?eh,tc_done,{group_timetrap_2_SUITE,{end_per_group,g11,[]},ok}}], + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(timetrap_all_no_ipg) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,14}}, + + {?eh,tc_done,{group_timetrap_3_SUITE,t1,{failed,{timetrap_timeout,1000}}}}, + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t11,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t21,{failed,{timetrap_timeout,1500}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}}], + + {?eh,tc_done,{group_timetrap_3_SUITE,t2,{failed,{timetrap_timeout,1000}}}}, + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t41,{failed,{timetrap_timeout,250}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_done,{group_timetrap_3_SUITE,t31,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t51,{failed,{timetrap_timeout,1500}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{ct_end_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}}], + + {?eh,tc_done,{group_timetrap_3_SUITE,t3,{failed,{timetrap_timeout,250}}}}, + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t61,{failed,{timetrap_timeout,500}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t81,{failed,{timetrap_timeout,750}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_done,{group_timetrap_3_SUITE,t71,{failed,{timetrap_timeout,500}}}}, + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t91,{failed,{timetrap_timeout,250}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{ct_end_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t101,{failed,{timetrap_timeout,1000}}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}}, + {?eh,tc_done,{group_timetrap_3_SUITE,t111,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,14,{0,0}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}}], + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(require) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,13}}, + {?eh,tc_done,{group_require_1_SUITE,init_per_suite,ok}}, + {?eh,tc_done,{group_require_1_SUITE,t1,ok}}, + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t11,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g1,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t21,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g2,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g3,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t31,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g3,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g4,[]}, + {skipped,{require_failed,{name_in_use,common2_alias,common2}}}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,t41, + {require_failed,{name_in_use,common2_alias,common2}}}}, + {?eh,test_stats,{4,0,{0,1}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group, + {require_failed,{name_in_use,common2_alias,common2}}}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g5,[]},ok}}, + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g6,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g6,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t61,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g6,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g6,[]},ok}}], + {?eh,tc_done,{group_require_1_SUITE,t51,ok}}, + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g7,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g7,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t71,ok}}, + {?eh,tc_done,{group_require_1_SUITE,t72,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g7,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g7,[]},ok}}], + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g5,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g8,[]}}}, + {?eh,tc_done,{group_require_1_SUITE, + {init_per_group,g8,[]}, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,t81, + {require_failed,{not_available,non_existing}}}}, + {?eh,test_stats,{8,0,{0,2}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group, + {require_failed,{not_available,non_existing}}}}], + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g9,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g9,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t91, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,test_stats,{8,0,{0,3}}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g9,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g9,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g10,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g10,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t101,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g10,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g10,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g11,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g11,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t111,ok}}, + {?eh,test_stats,{10,0,{0,3}}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g11,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g11,[]},ok}}], + + {?eh,tc_done,{group_require_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(require_default) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,13}}, + {?eh,tc_done,{group_require_1_SUITE,init_per_suite,ok}}, + {?eh,tc_done,{group_require_1_SUITE,t1,ok}}, + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t11,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g1,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t21,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g2,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g3,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t31,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g3,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{group_require_1_SUITE, + {init_per_group,g4,[]}, + {skipped,{require_failed,{not_available,common3}}}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,t41, + {require_failed,{not_available,common3}}}}, + {?eh,test_stats,{4,0,{0,1}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group, + {require_failed,{not_available,common3}}}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g5,[]},ok}}, + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g6,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g6,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t61,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g6,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g6,[]},ok}}], + {?eh,tc_done,{group_require_1_SUITE,t51,ok}}, + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g7,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g7,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t71,ok}}, + {?eh,tc_done,{group_require_1_SUITE,t72,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g7,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g7,[]},ok}}], + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g5,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g8,[]}}}, + {?eh,tc_done,{group_require_1_SUITE, + {init_per_group,g8,[]}, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,t81, + {require_failed,{not_available,non_existing}}}}, + {?eh,test_stats,{8,0,{0,2}}}, + {?eh,tc_auto_skip,{group_require_1_SUITE,end_per_group, + {require_failed,{not_available,non_existing}}}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g9,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g9,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t91, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,test_stats,{8,0,{0,3}}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g9,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g9,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g10,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g10,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t101,ok}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g10,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g10,[]},ok}}], + + [{?eh,tc_start,{group_require_1_SUITE,{init_per_group,g11,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{init_per_group,g11,[]},ok}}, + {?eh,tc_done,{group_require_1_SUITE,t111,ok}}, + {?eh,test_stats,{10,0,{0,3}}}, + {?eh,tc_start,{group_require_1_SUITE,{end_per_group,g11,[]}}}, + {?eh,tc_done,{group_require_1_SUITE,{end_per_group,g11,[]},ok}}], + + {?eh,tc_done,{group_require_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(require_no_ips) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,13}}, + {?eh,tc_done,{group_require_2_SUITE,t1,ok}}, + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t11,ok}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g1,[]},ok}}], + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t21,ok}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g2,[]},ok}}], + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g3,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g3,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t31,ok}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g3,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g3,[]},ok}}], + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g4,[]}, + {skipped,{require_failed,{name_in_use,common2_alias,common2}}}}}, + {?eh,tc_auto_skip,{group_require_2_SUITE,t41, + {require_failed,{name_in_use,common2_alias,common2}}}}, + {?eh,test_stats,{4,0,{0,1}}}, + {?eh,tc_auto_skip,{group_require_2_SUITE,end_per_group, + {require_failed,{name_in_use,common2_alias,common2}}}}], + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g5,[]},ok}}, + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g6,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g6,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t61,ok}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g6,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g6,[]},ok}}], + {?eh,tc_done,{group_require_2_SUITE,t51,ok}}, + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g7,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g7,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t71,ok}}, + {?eh,tc_done,{group_require_2_SUITE,t72,ok}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g7,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g7,[]},ok}}], + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g5,[]},ok}}], + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g8,[]}}}, + {?eh,tc_done,{group_require_2_SUITE, + {init_per_group,g8,[]}, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,tc_auto_skip,{group_require_2_SUITE,t81, + {require_failed,{not_available,non_existing}}}}, + {?eh,test_stats,{8,0,{0,2}}}, + {?eh,tc_auto_skip,{group_require_2_SUITE,end_per_group, + {require_failed,{not_available,non_existing}}}}], + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g9,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g9,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t91, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,test_stats,{8,0,{0,3}}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g9,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g9,[]},ok}}], + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g10,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g10,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t101,ok}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g10,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g10,[]},ok}}], + + [{?eh,tc_start,{group_require_2_SUITE,{init_per_group,g11,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{init_per_group,g11,[]},ok}}, + {?eh,tc_done,{group_require_2_SUITE,t111,ok}}, + {?eh,test_stats,{10,0,{0,3}}}, + {?eh,tc_start,{group_require_2_SUITE,{end_per_group,g11,[]}}}, + {?eh,tc_done,{group_require_2_SUITE,{end_per_group,g11,[]},ok}}], + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(require_no_ipg) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,13}}, + {?eh,tc_done,{group_require_3_SUITE,t1,ok}}, + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g1,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g1,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t11,ok}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g1,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g1,[{suite,group_require_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g2,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g2,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t21,ok}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g2,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g2,[{suite,group_require_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g3,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g3,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t31,ok}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g3,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g3,[{suite,group_require_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g4,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g4,[{suite,group_require_3_SUITE}]}, + {skipped,{require_failed,{name_in_use,common2_alias,common2}}}}}, + {?eh,tc_auto_skip,{group_require_3_SUITE,t41, + {require_failed,{name_in_use,common2_alias,common2}}}}, + {?eh,test_stats,{4,0,{0,1}}}, + {?eh,tc_auto_skip,{ct_framework,ct_end_per_group, + {require_failed,{name_in_use,common2_alias,common2}}}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g5,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g5,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g6,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g6,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t61,ok}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g6,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g6,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_done,{group_require_3_SUITE,t51,ok}}, + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g7,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g7,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t71,ok}}, + {?eh,tc_done,{group_require_3_SUITE,t72,ok}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g7,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g7,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{ct_end_per_group,g5,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g5,[{suite,group_require_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g8,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g8,[{suite,group_require_3_SUITE}]}, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,tc_auto_skip,{group_require_3_SUITE,t81, + {require_failed,{not_available,non_existing}}}}, + {?eh,test_stats,{8,0,{0,2}}}, + {?eh,tc_auto_skip,{ct_framework,ct_end_per_group, + {require_failed,{not_available,non_existing}}}}], + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g9,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g9,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t91, + {skipped,{require_failed,{not_available,non_existing}}}}}, + {?eh,test_stats,{8,0,{0,3}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g9,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g9,[{suite,group_require_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g10,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g10,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t101,ok}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g10,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g10,[{suite,group_require_3_SUITE}]},ok}}], + + [{?eh,tc_start,{ct_framework,{ct_init_per_group,g11,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,g11,[{suite,group_require_3_SUITE}]},ok}}, + {?eh,tc_done,{group_require_3_SUITE,t111,ok}}, + {?eh,test_stats,{10,0,{0,3}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,g11,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,g11,[{suite,group_require_3_SUITE}]},ok}}], + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]. + + diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_require_1_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_require_1_SUITE.erl new file mode 100644 index 0000000000..16df897752 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE_data/group_require_1_SUITE.erl @@ -0,0 +1,259 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(group_require_1_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + + +%%%----------------------------------------------------------------- +%%% CONFIG FUNCS +%%%----------------------------------------------------------------- + +init_per_suite(Config) -> + ct:comment(io_lib:format("init( ~w ): ~p", [?MODULE, suite()])), + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + Info = case catch group(G) of {'EXIT',_} -> []; I -> I end, + ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])), + if Info /= [] -> verify_cfg(G); true -> ok end, + Config. + +end_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + Info = case catch group(G) of {'EXIT',_} -> []; I -> I end, + ct:comment(io_lib:format("end( ~w )", [G])), + if Info /= [] -> verify_cfg(G); true -> ok end, + ok. + +init_per_testcase(t101, Config) -> + Config; +init_per_testcase(t111, Config) -> + Config; +init_per_testcase(TestCase, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = if GrProps == undefined -> []; true -> GrProps end, + verify_cfg(proplists:get_value(name, GrProps1)), + if TestCase == t72 -> verify_cfg(TestCase); true -> ok end, + Info = case catch apply(?MODULE,TestCase,[]) of + {'EXIT',_} -> []; + I -> I + end, + ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])), + Config. + +end_per_testcase(t101, Config) -> + ok; +end_per_testcase(t111, Config) -> + ok; +end_per_testcase(TestCase, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = if GrProps == undefined -> []; true -> GrProps end, + verify_cfg(proplists:get_value(name, GrProps1)), + if TestCase == t72 -> verify_cfg(TestCase); true -> ok end, + ok. + +verify_cfg(undefined) -> + ok; +verify_cfg(Name) -> + Key = list_to_atom(atom_to_list(Name) ++ "_cfg"), + Alias = list_to_atom(atom_to_list(Name) ++ "_cfg_alias"), + Val = list_to_atom(atom_to_list(Name) ++ "_cfg_val"), + ct:pal("Reading ~p & ~p. Expecting ~p.", [Key,Alias,Val]), + Val = ct:get_config(Key), + Val = ct:get_config(Alias), + suite_cfg_val = ct:get_config(suite_cfg), + suite_cfg_val = ct:get_config(suite_cfg_alias). + + + +%%%------------------------------------------------------------------ +%%% TEST DECLARATIONS +%%%------------------------------------------------------------------ + +groups() -> + [{g1,[],[t11]}, + {g2,[],[t21]}, + {g3,[],[t31]}, + {g4,[],[t41]}, + + {g5,[],[{group,g6},t51,{group,g7}]}, + + {g6,[],[t61]}, + {g7,[],[t71,t72]}, + + {g8,[],[t81]}, + {g9,[],[t91]}, + {g10,[],[t101]}, + {g11,[],[t111]} + ]. + + +all() -> + [t1, + {group,g1}, + {group,g2}, + {group,g3}, + {group,g4}, + {group,g5}, + {group,g8}, + {group,g9}, + {group,g10}, + {group,g11} + ]. + +%%%----------------------------------------------------------------- +%%% INFO FUNCS +%%%----------------------------------------------------------------- + +suite() -> [{require,suite_cfg}, + {require,suite_cfg_alias,suite_cfg}, + {require,common1}, + {default_config,suite_cfg,suite_cfg_val}, + {default_config,common1,common1_val}]. + +group(g1) -> [{require,g1_cfg}, + {require,g1_cfg_alias,g1_cfg}, + {default_config,g1_cfg,g1_cfg_val}]; + +group(g2) -> [{require,g2_cfg}, + {require,g2_cfg_alias,g2_cfg}, + {require,common1}, + {require,common2}, + {default_config,g2_cfg,g2_cfg_val}, + {default_config,common1,common1_val}, + {default_config,common2,common2_val}]; + +group(g3) -> [{require,g3_cfg}, + {require,g3_cfg_alias,g3_cfg}, + {require,common2}, + {require,common2_alias,common2}, + {default_config,g3_cfg,g3_cfg_val}, + {default_config,common2,common2_val}]; + +group(g4) -> [{require,g4_cfg}, + {require,g4_cfg_alias,g4_cfg}, + {require,common2_alias,common3}, + {default_config,g4_cfg,g4_cfg_val}]; + +group(g5) -> [{require,g5_cfg}, + {require,g5_cfg_alias,g5_cfg}, + {default_config,g5_cfg,g5_cfg_val}]; + +group(g6) -> [{require,g6_cfg}, + {require,g6_cfg_alias,g6_cfg}, + {default_config,g6_cfg,g6_cfg_val}]; + +group(g7) -> [{require,g7_cfg}, + {require,g7_cfg_alias,g7_cfg}, + {default_config,g7_cfg,g7_cfg_val}]; + +group(g8) -> [{require,non_existing}]; + +group(g9) -> [{require,g9_cfg}, + {require,g9_cfg_alias,g9_cfg}, + {default_config,g9_cfg,g9_cfg_val}]; + +group(G) when G /= g11 -> []. + +t72() -> [{require,t72_cfg}, + {require,t72_cfg_alias,t72_cfg}, + {default_config,t72_cfg,t72_cfg_val}]. + +t91() -> [{require,non_existing}]. + + +%%%------------------------------------------------------------------ +%%% TEST CASES +%%%------------------------------------------------------------------ + +t1(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + +t11(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + suite_cfg_val = ct:get_config(suite_cfg_alias), + g1_cfg_val = ct:get_config(g1_cfg), + g1_cfg_val = ct:get_config(g1_cfg_alias). + +t21(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g2_cfg_val = ct:get_config(g2_cfg), + g2_cfg_val = ct:get_config(g2_cfg_alias), + common1_val = ct:get_config(common1), + common2_val = ct:get_config(common2). + +t31(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g3_cfg_val = ct:get_config(g3_cfg), + g3_cfg_val = ct:get_config(g3_cfg_alias), + common2_val = ct:get_config(common2), + common2_val = ct:get_config(common2_alias). + +t41(_) -> + exit(should_be_skipped). + +t51(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias). + +t61(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g6_cfg_val = ct:get_config(g6_cfg), + g6_cfg_val = ct:get_config(g6_cfg_alias). + +t71(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g7_cfg_val = ct:get_config(g7_cfg), + g7_cfg_val = ct:get_config(g7_cfg_alias). + +t72(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g7_cfg_val = ct:get_config(g7_cfg), + g7_cfg_val = ct:get_config(g7_cfg_alias), + t72_cfg_val = ct:get_config(t72_cfg). + +t81(_) -> + exit(should_be_skipped). + +t91(_) -> + exit(should_be_skipped). + +t101(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + +t111(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + + diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_require_2_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_require_2_SUITE.erl new file mode 100644 index 0000000000..adb53ff564 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE_data/group_require_2_SUITE.erl @@ -0,0 +1,252 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(group_require_2_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + + +%%%----------------------------------------------------------------- +%%% CONFIG FUNCS +%%%----------------------------------------------------------------- + +init_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + Info = case catch group(G) of {'EXIT',_} -> []; I -> I end, + ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])), + if Info /= [] -> verify_cfg(G); true -> ok end, + Config. + +end_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + Info = case catch group(G) of {'EXIT',_} -> []; I -> I end, + ct:comment(io_lib:format("end( ~w )", [G])), + if Info /= [] -> verify_cfg(G); true -> ok end, + ok. + +init_per_testcase(t101, Config) -> + Config; +init_per_testcase(t111, Config) -> + Config; +init_per_testcase(TestCase, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = if GrProps == undefined -> []; true -> GrProps end, + verify_cfg(proplists:get_value(name, GrProps1)), + if TestCase == t72 -> verify_cfg(TestCase); true -> ok end, + Info = case catch apply(?MODULE,TestCase,[]) of + {'EXIT',_} -> []; + I -> I + end, + ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])), + Config. + +end_per_testcase(t101, Config) -> + ok; +end_per_testcase(t111, Config) -> + ok; +end_per_testcase(TestCase, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = if GrProps == undefined -> []; true -> GrProps end, + verify_cfg(proplists:get_value(name, GrProps1)), + if TestCase == t72 -> verify_cfg(TestCase); true -> ok end, + ok. + +verify_cfg(undefined) -> + ok; +verify_cfg(Name) -> + Key = list_to_atom(atom_to_list(Name) ++ "_cfg"), + Alias = list_to_atom(atom_to_list(Name) ++ "_cfg_alias"), + Val = list_to_atom(atom_to_list(Name) ++ "_cfg_val"), + ct:pal("Reading ~p & ~p. Expecting ~p.", [Key,Alias,Val]), + Val = ct:get_config(Key), + Val = ct:get_config(Alias), + suite_cfg_val = ct:get_config(suite_cfg), + suite_cfg_val = ct:get_config(suite_cfg_alias). + + + +%%%------------------------------------------------------------------ +%%% TEST DECLARATIONS +%%%------------------------------------------------------------------ + +groups() -> + [{g1,[],[t11]}, + {g2,[],[t21]}, + {g3,[],[t31]}, + {g4,[],[t41]}, + + {g5,[],[{group,g6},t51,{group,g7}]}, + + {g6,[],[t61]}, + {g7,[],[t71,t72]}, + + {g8,[],[t81]}, + {g9,[],[t91]}, + {g10,[],[t101]}, + {g11,[],[t111]} + ]. + + +all() -> + [t1, + {group,g1}, + {group,g2}, + {group,g3}, + {group,g4}, + {group,g5}, + {group,g8}, + {group,g9}, + {group,g10}, + {group,g11} + ]. + +%%%----------------------------------------------------------------- +%%% INFO FUNCS +%%%----------------------------------------------------------------- + +suite() -> [{require,suite_cfg}, + {require,suite_cfg_alias,suite_cfg}, + {require,common1}, + {default_config,suite_cfg,suite_cfg_val}, + {default_config,common1,common1_val}]. + +group(g1) -> [{require,g1_cfg}, + {require,g1_cfg_alias,g1_cfg}, + {default_config,g1_cfg,g1_cfg_val}]; + +group(g2) -> [{require,g2_cfg}, + {require,g2_cfg_alias,g2_cfg}, + {require,common1}, + {require,common2}, + {default_config,g2_cfg,g2_cfg_val}, + {default_config,common1,common1_val}, + {default_config,common2,common2_val}]; + +group(g3) -> [{require,g3_cfg}, + {require,g3_cfg_alias,g3_cfg}, + {require,common2}, + {require,common2_alias,common2}, + {default_config,g3_cfg,g3_cfg_val}, + {default_config,common2,common2_val}]; + +group(g4) -> [{require,g4_cfg}, + {require,g4_cfg_alias,g4_cfg}, + {require,common2_alias,common3}, + {default_config,g4_cfg,g4_cfg_val}]; + +group(g5) -> [{require,g5_cfg}, + {require,g5_cfg_alias,g5_cfg}, + {default_config,g5_cfg,g5_cfg_val}]; + +group(g6) -> [{require,g6_cfg}, + {require,g6_cfg_alias,g6_cfg}, + {default_config,g6_cfg,g6_cfg_val}]; + +group(g7) -> [{require,g7_cfg}, + {require,g7_cfg_alias,g7_cfg}, + {default_config,g7_cfg,g7_cfg_val}]; + +group(g8) -> [{require,non_existing}]; + +group(g9) -> [{require,g9_cfg}, + {require,g9_cfg_alias,g9_cfg}, + {default_config,g9_cfg,g9_cfg_val}]; + +group(G) when G /= g11 -> []. + +t72() -> [{require,t72_cfg}, + {require,t72_cfg_alias,t72_cfg}, + {default_config,t72_cfg,t72_cfg_val}]. + +t91() -> [{require,non_existing}]. + + +%%%------------------------------------------------------------------ +%%% TEST CASES +%%%------------------------------------------------------------------ + +t1(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + +t11(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + suite_cfg_val = ct:get_config(suite_cfg_alias), + g1_cfg_val = ct:get_config(g1_cfg), + g1_cfg_val = ct:get_config(g1_cfg_alias). + +t21(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g2_cfg_val = ct:get_config(g2_cfg), + g2_cfg_val = ct:get_config(g2_cfg_alias), + common1_val = ct:get_config(common1), + common2_val = ct:get_config(common2). + +t31(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g3_cfg_val = ct:get_config(g3_cfg), + g3_cfg_val = ct:get_config(g3_cfg_alias), + common2_val = ct:get_config(common2), + common2_val = ct:get_config(common2_alias). + +t41(_) -> + exit(should_be_skipped). + +t51(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias). + +t61(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g6_cfg_val = ct:get_config(g6_cfg), + g6_cfg_val = ct:get_config(g6_cfg_alias). + +t71(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g7_cfg_val = ct:get_config(g7_cfg), + g7_cfg_val = ct:get_config(g7_cfg_alias). + +t72(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g7_cfg_val = ct:get_config(g7_cfg), + g7_cfg_val = ct:get_config(g7_cfg_alias), + t72_cfg_val = ct:get_config(t72_cfg). + +t81(_) -> + exit(should_be_skipped). + +t91(_) -> + exit(should_be_skipped). + +t101(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + +t111(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + + diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_require_3_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_require_3_SUITE.erl new file mode 100644 index 0000000000..1f2dfd2a30 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE_data/group_require_3_SUITE.erl @@ -0,0 +1,241 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(group_require_3_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + + +%%%----------------------------------------------------------------- +%%% CONFIG FUNCS +%%%----------------------------------------------------------------- + +%% init_per_suite(Config) -> +%% Config. +%% end_per_suite(_) -> +%% ok. + +init_per_testcase(t101, Config) -> + Config; +init_per_testcase(t111, Config) -> + Config; +init_per_testcase(TestCase, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = if GrProps == undefined -> []; true -> GrProps end, + verify_cfg(proplists:get_value(name, GrProps1)), + if TestCase == t72 -> verify_cfg(TestCase); true -> ok end, + Info = case catch apply(?MODULE,TestCase,[]) of + {'EXIT',_} -> []; + I -> I + end, + ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])), + Config. + +end_per_testcase(t101, _Config) -> + ok; +end_per_testcase(t111, _Config) -> + ok; +end_per_testcase(TestCase, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = if GrProps == undefined -> []; true -> GrProps end, + verify_cfg(proplists:get_value(name, GrProps1)), + if TestCase == t72 -> verify_cfg(TestCase); true -> ok end, + ok. + +verify_cfg(undefined) -> + ok; +verify_cfg(Name) -> + Key = list_to_atom(atom_to_list(Name) ++ "_cfg"), + Alias = list_to_atom(atom_to_list(Name) ++ "_cfg_alias"), + Val = list_to_atom(atom_to_list(Name) ++ "_cfg_val"), + ct:pal("Reading ~p & ~p. Expecting ~p.", [Key,Alias,Val]), + Val = ct:get_config(Key), + Val = ct:get_config(Alias), + suite_cfg_val = ct:get_config(suite_cfg), + suite_cfg_val = ct:get_config(suite_cfg_alias). + + + +%%%------------------------------------------------------------------ +%%% TEST DECLARATIONS +%%%------------------------------------------------------------------ + +groups() -> + [{g1,[],[t11]}, + {g2,[],[t21]}, + {g3,[],[t31]}, + {g4,[],[t41]}, + + {g5,[],[{group,g6},t51,{group,g7}]}, + + {g6,[],[t61]}, + {g7,[],[t71,t72]}, + + {g8,[],[t81]}, + {g9,[],[t91]}, + {g10,[],[t101]}, + {g11,[],[t111]} + ]. + + +all() -> + [t1, + {group,g1}, + {group,g2}, + {group,g3}, + {group,g4}, + {group,g5}, + {group,g8}, + {group,g9}, + {group,g10}, + {group,g11} + ]. + +%%%----------------------------------------------------------------- +%%% INFO FUNCS +%%%----------------------------------------------------------------- + +suite() -> [{require,suite_cfg}, + {require,suite_cfg_alias,suite_cfg}, + {require,common1}, + {default_config,suite_cfg,suite_cfg_val}, + {default_config,common1,common1_val}]. + +group(g1) -> [{require,g1_cfg}, + {require,g1_cfg_alias,g1_cfg}, + {default_config,g1_cfg,g1_cfg_val}]; + +group(g2) -> [{require,g2_cfg}, + {require,g2_cfg_alias,g2_cfg}, + {require,common1}, + {require,common2}, + {default_config,g2_cfg,g2_cfg_val}, + {default_config,common1,common1_val}, + {default_config,common2,common2_val}]; + +group(g3) -> [{require,g3_cfg}, + {require,g3_cfg_alias,g3_cfg}, + {require,common2}, + {require,common2_alias,common2}, + {default_config,g3_cfg,g3_cfg_val}, + {default_config,common2,common2_val}]; + +group(g4) -> [{require,g4_cfg}, + {require,g4_cfg_alias,g4_cfg}, + {require,common2_alias,common3}, + {default_config,g4_cfg,g4_cfg_val}]; + +group(g5) -> [{require,g5_cfg}, + {require,g5_cfg_alias,g5_cfg}, + {default_config,g5_cfg,g5_cfg_val}]; + +group(g6) -> [{require,g6_cfg}, + {require,g6_cfg_alias,g6_cfg}, + {default_config,g6_cfg,g6_cfg_val}]; + +group(g7) -> [{require,g7_cfg}, + {require,g7_cfg_alias,g7_cfg}, + {default_config,g7_cfg,g7_cfg_val}]; + +group(g8) -> [{require,non_existing}]; + +group(g9) -> [{require,g9_cfg}, + {require,g9_cfg_alias,g9_cfg}, + {default_config,g9_cfg,g9_cfg_val}]; + +group(G) when G /= g11 -> []. + +t72() -> [{require,t72_cfg}, + {require,t72_cfg_alias,t72_cfg}, + {default_config,t72_cfg,t72_cfg_val}]. + +t91() -> [{require,non_existing}]. + + +%%%------------------------------------------------------------------ +%%% TEST CASES +%%%------------------------------------------------------------------ + +t1(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + +t11(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + suite_cfg_val = ct:get_config(suite_cfg_alias), + g1_cfg_val = ct:get_config(g1_cfg), + g1_cfg_val = ct:get_config(g1_cfg_alias). + +t21(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g2_cfg_val = ct:get_config(g2_cfg), + g2_cfg_val = ct:get_config(g2_cfg_alias), + common1_val = ct:get_config(common1), + common2_val = ct:get_config(common2). + +t31(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g3_cfg_val = ct:get_config(g3_cfg), + g3_cfg_val = ct:get_config(g3_cfg_alias), + common2_val = ct:get_config(common2), + common2_val = ct:get_config(common2_alias). + +t41(_) -> + exit(should_be_skipped). + +t51(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias). + +t61(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g6_cfg_val = ct:get_config(g6_cfg), + g6_cfg_val = ct:get_config(g6_cfg_alias). + +t71(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g7_cfg_val = ct:get_config(g7_cfg), + g7_cfg_val = ct:get_config(g7_cfg_alias). + +t72(_) -> + suite_cfg_val = ct:get_config(suite_cfg), + g5_cfg_val = ct:get_config(g5_cfg), + g5_cfg_val = ct:get_config(g5_cfg_alias), + g7_cfg_val = ct:get_config(g7_cfg), + g7_cfg_val = ct:get_config(g7_cfg_alias), + t72_cfg_val = ct:get_config(t72_cfg). + +t81(_) -> + exit(should_be_skipped). + +t91(_) -> + exit(should_be_skipped). + +t101(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + +t111(_) -> + suite_cfg_val = ct:get_config(suite_cfg). + + diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_1_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_1_SUITE.erl new file mode 100644 index 0000000000..0a81edf729 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_1_SUITE.erl @@ -0,0 +1,191 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(group_timetrap_1_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + + +%%%----------------------------------------------------------------- +%%% CONFIG FUNCS +%%%----------------------------------------------------------------- + +init_per_suite(Config) -> + ct:comment(io_lib:format("init( ~w ): ~p", [?MODULE, suite()])), + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + Info = case catch group(G) of {'EXIT',_} -> []; I -> I end, + ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])), + Config. + +end_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + ct:comment(io_lib:format("end( ~w )", [G])), + ok. + +init_per_testcase(TestCase, Config) -> + Info = case catch apply(?MODULE,TestCase,[]) of + {'EXIT',_} -> []; + I -> I + end, + ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])), + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +%%%------------------------------------------------------------------ +%%% TEST DECLARATIONS +%%%------------------------------------------------------------------ + +groups() -> + [{g1,[],[t11]}, + {g2,[],[t21]}, + {g3,[],[{group,g4},t31,{group,g5}]}, + + {g4,[],[t41]}, + {g5,[],[t51]}, + + {g6,[],[t61]}, + {g7,[],[{group,g8},t71,{group,g9}]}, + + {g8,[],[t81]}, + {g9,[],[t91]}, + + {g10,[],[t101]}, + {g11,[],[t111]} + ]. + + +all() -> + [t1, + {group,g1}, + {group,g2}, + t2, + {group,g3}, + t3, + {group,g6}, + {group,g7}, + {group,g10}, + {group,g11} + ]. + +%%%----------------------------------------------------------------- +%%% INFO FUNCS +%%%----------------------------------------------------------------- + +suite() -> [{timetrap,1000}]. + +group(g1) -> [{timetrap,500}]; + +group(g2) -> [{timetrap,1500}]; + +group(g3) -> [{timetrap,500}]; + +group(g4) -> [{timetrap,250}]; + +group(g5) -> [{timetrap,1500}]; + +group(g6) -> [{timetrap,250}]; + +group(g7) -> [{timetrap,250}]; + +group(g8) -> [{timetrap,250}]; + +group(G) when G /= g11 -> []. + +t3() -> [{timetrap,250}]. + +t61() -> [{timetrap,500}]. + +t71() -> [{timetrap,500}]. + +t81() -> [{timetrap,750}]. + +t91() -> [{timetrap,250}]. + +%%%------------------------------------------------------------------ +%%% TEST CASES +%%%------------------------------------------------------------------ + +t1(_) -> + ct:sleep(3000), + exit(should_timeout). + +t11(_) -> + ct:sleep(750), + exit(should_timeout). + +t21(_) -> + ct:sleep(3000), + exit(should_timeout). + +t2(_) -> + ct:sleep(1250), + exit(should_timeout). + +t31(_) -> + ct:sleep(750), + exit(should_timeout). + +t41(_) -> + ct:sleep(350), + exit(should_timeout). + +t51(_) -> + ct:sleep(2000), + exit(should_timeout). + +t3(_) -> + ct:sleep(500), + exit(should_timeout). + +t61(_) -> + ct:sleep(750), + exit(should_timeout). + +t71(_) -> + ct:sleep(750), + exit(should_timeout). + +t81(_) -> + ct:sleep(1000), + exit(should_timeout). + +t91(_) -> + ct:sleep(350), + exit(should_timeout). + +t101(_) -> + ct:sleep(1500), + exit(should_timeout). + +t111(_) -> + ct:sleep(1500), + exit(should_timeout). + + diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_2_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_2_SUITE.erl new file mode 100644 index 0000000000..1ebe8bd510 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_2_SUITE.erl @@ -0,0 +1,184 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(group_timetrap_2_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + + +%%%----------------------------------------------------------------- +%%% CONFIG FUNCS +%%%----------------------------------------------------------------- + +init_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + Info = case catch group(G) of {'EXIT',_} -> []; I -> I end, + ct:comment(io_lib:format("init( ~w ): ~p", [G, Info])), + Config. + +end_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + _GrProps1 = proplists:delete(name, GrProps), + ct:comment(io_lib:format("end( ~w )", [G])), + ok. + +init_per_testcase(TestCase, Config) -> + Info = case catch apply(?MODULE,TestCase,[]) of + {'EXIT',_} -> []; + I -> I + end, + ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])), + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +%%%------------------------------------------------------------------ +%%% TEST DECLARATIONS +%%%------------------------------------------------------------------ + +groups() -> + [{g1,[],[t11]}, + {g2,[],[t21]}, + {g3,[],[{group,g4},t31,{group,g5}]}, + + {g4,[],[t41]}, + {g5,[],[t51]}, + + {g6,[],[t61]}, + {g7,[],[{group,g8},t71,{group,g9}]}, + + {g8,[],[t81]}, + {g9,[],[t91]}, + + {g10,[],[t101]}, + {g11,[],[t111]} + ]. + + +all() -> + [t1, + {group,g1}, + {group,g2}, + t2, + {group,g3}, + t3, + {group,g6}, + {group,g7}, + {group,g10}, + {group,g11} + ]. + +%%%----------------------------------------------------------------- +%%% INFO FUNCS +%%%----------------------------------------------------------------- + +suite() -> [{timetrap,1000}]. + +group(g1) -> [{timetrap,500}]; + +group(g2) -> [{timetrap,1500}]; + +group(g3) -> [{timetrap,500}]; + +group(g4) -> [{timetrap,250}]; + +group(g5) -> [{timetrap,1500}]; + +group(g6) -> [{timetrap,250}]; + +group(g7) -> [{timetrap,250}]; + +group(g8) -> [{timetrap,250}]; + +group(G) when G /= g11 -> []. + +t3() -> [{timetrap,250}]. + +t61() -> [{timetrap,500}]. + +t71() -> [{timetrap,500}]. + +t81() -> [{timetrap,750}]. + +t91() -> [{timetrap,250}]. + +%%%------------------------------------------------------------------ +%%% TEST CASES +%%%------------------------------------------------------------------ + +t1(_) -> + ct:sleep(3000), + exit(should_timeout). + +t11(_) -> + ct:sleep(750), + exit(should_timeout). + +t21(_) -> + ct:sleep(3000), + exit(should_timeout). + +t2(_) -> + ct:sleep(1250), + exit(should_timeout). + +t31(_) -> + ct:sleep(750), + exit(should_timeout). + +t41(_) -> + ct:sleep(350), + exit(should_timeout). + +t51(_) -> + ct:sleep(2000), + exit(should_timeout). + +t3(_) -> + ct:sleep(500), + exit(should_timeout). + +t61(_) -> + ct:sleep(750), + exit(should_timeout). + +t71(_) -> + ct:sleep(750), + exit(should_timeout). + +t81(_) -> + ct:sleep(1000), + exit(should_timeout). + +t91(_) -> + ct:sleep(350), + exit(should_timeout). + +t101(_) -> + ct:sleep(1500), + exit(should_timeout). + +t111(_) -> + ct:sleep(1500), + exit(should_timeout). + + diff --git a/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_3_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_3_SUITE.erl new file mode 100644 index 0000000000..66d29802e2 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE_data/group_timetrap_3_SUITE.erl @@ -0,0 +1,171 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(group_timetrap_3_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + + +%%%----------------------------------------------------------------- +%%% CONFIG FUNCS +%%%----------------------------------------------------------------- + +init_per_testcase(TestCase, Config) -> + Info = case catch apply(?MODULE,TestCase,[]) of + {'EXIT',_} -> []; + I -> I + end, + ct:comment(io_lib:format("init( ~w ): ~p", [TestCase, Info])), + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +%%%------------------------------------------------------------------ +%%% TEST DECLARATIONS +%%%------------------------------------------------------------------ + +groups() -> + [{g1,[],[t11]}, + {g2,[],[t21]}, + {g3,[],[{group,g4},t31,{group,g5}]}, + + {g4,[],[t41]}, + {g5,[],[t51]}, + + {g6,[],[t61]}, + {g7,[],[{group,g8},t71,{group,g9}]}, + + {g8,[],[t81]}, + {g9,[],[t91]}, + + {g10,[],[t101]}, + {g11,[],[t111]} + ]. + + +all() -> + [t1, + {group,g1}, + {group,g2}, + t2, + {group,g3}, + t3, + {group,g6}, + {group,g7}, + {group,g10}, + {group,g11} + ]. + +%%%----------------------------------------------------------------- +%%% INFO FUNCS +%%%----------------------------------------------------------------- + +suite() -> [{timetrap,1000}]. + +group(g1) -> [{timetrap,500}]; + +group(g2) -> [{timetrap,1500}]; + +group(g3) -> [{timetrap,500}]; + +group(g4) -> [{timetrap,250}]; + +group(g5) -> [{timetrap,1500}]; + +group(g6) -> [{timetrap,250}]; + +group(g7) -> [{timetrap,250}]; + +group(g8) -> [{timetrap,250}]; + +group(G) when G /= g11 -> []. + +t3() -> [{timetrap,250}]. + +t61() -> [{timetrap,500}]. + +t71() -> [{timetrap,500}]. + +t81() -> [{timetrap,750}]. + +t91() -> [{timetrap,250}]. + +%%%------------------------------------------------------------------ +%%% TEST CASES +%%%------------------------------------------------------------------ + +t1(_) -> + ct:sleep(3000), + exit(should_timeout). + +t11(_) -> + ct:sleep(750), + exit(should_timeout). + +t21(_) -> + ct:sleep(3000), + exit(should_timeout). + +t2(_) -> + ct:sleep(1250), + exit(should_timeout). + +t31(_) -> + ct:sleep(750), + exit(should_timeout). + +t41(_) -> + ct:sleep(350), + exit(should_timeout). + +t51(_) -> + ct:sleep(2000), + exit(should_timeout). + +t3(_) -> + ct:sleep(500), + exit(should_timeout). + +t61(_) -> + ct:sleep(750), + exit(should_timeout). + +t71(_) -> + ct:sleep(750), + exit(should_timeout). + +t81(_) -> + ct:sleep(1000), + exit(should_timeout). + +t91(_) -> + ct:sleep(350), + exit(should_timeout). + +t101(_) -> + ct:sleep(1500), + exit(should_timeout). + +t111(_) -> + ct:sleep(1500), + exit(should_timeout). + + diff --git a/lib/common_test/test/ct_group_info_SUITE_data/vars.cfg b/lib/common_test/test/ct_group_info_SUITE_data/vars.cfg new file mode 100644 index 0000000000..8a1960d121 --- /dev/null +++ b/lib/common_test/test/ct_group_info_SUITE_data/vars.cfg @@ -0,0 +1,19 @@ +{suite_cfg,suite_cfg_val}. +{g1_cfg,g1_cfg_val}. +{g2_cfg,g2_cfg_val}. +{g3_cfg,g3_cfg_val}. +{g4_cfg,g4_cfg_val}. +{g5_cfg,g5_cfg_val}. +{g6_cfg,g6_cfg_val}. +{g7_cfg,g7_cfg_val}. +{g8_cfg,g8_cfg_val}. +{g9_cfg,g9_cfg_val}. +{g10_cfg,g10_cfg_val}. +{g11_cfg,g11_cfg_val}. + +{t72_cfg,t72_cfg_val}. +{t91_cfg,t91_cfg_val}. + +{common1,common1_val}. +{common2,common2_val}. +{common3,common3_val}. diff --git a/lib/common_test/test/ct_groups_spec_SUITE.erl b/lib/common_test/test/ct_groups_spec_SUITE.erl new file mode 100644 index 0000000000..5a6d5ac0ac --- /dev/null +++ b/lib/common_test/test/ct_groups_spec_SUITE.erl @@ -0,0 +1,586 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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: ct_groups_spec_SUITE +%%% +%%% Description: +%%% Test that overriding default group properties with group terms +%%% in all/0 and in test specifications works as expected. +%%% +%%%------------------------------------------------------------------- +-module(ct_groups_spec_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config1 = ct_test_support:init_per_suite(Config), + Config1. + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + ct_test_support:end_per_testcase(TestCase, Config). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + simple_group_opt, + simple_group_case_opt, + override_with_all, + override_with_spec + ]. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +simple_group_opt(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "groups_spec_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{group,[g1,g5]}, + {label,simple_group_opt}], Config), + ok = execute(simple_group_opt, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +simple_group_case_opt(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "groups_spec_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{group,g5},{testcase,[t52,t54]}, + {label,simple_group_case_opt}], Config), + ok = execute(simple_group_case_opt, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +override_with_all(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "groups_spec_1_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{label,override_with_all}], Config), + ok = execute(override_with_all, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +override_with_spec(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "override.spec"), + {Opts,ERPid} = setup([{spec,Spec},{label,override_with_spec}], Config), + ok = execute(override_with_spec, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +execute(Name, Opts, ERPid, Config) -> + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(Name, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(Name), + ct_test_support:verify_events(TestEvents, Events, Config). + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). + +%%%----------------------------------------------------------------- +%%% TEST EVENTS +%%%----------------------------------------------------------------- +events_to_check(Test) -> + %% 2 tests (ct:run_test + script_start) is default + events_to_check(Test, 2). + +events_to_check(_, 0) -> + []; +events_to_check(Test, N) -> + test_events(Test) ++ events_to_check(Test, N-1). + + +test_events(simple_group_opt) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,start_info,{1,1,7}}, + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}}, + {?eh,test_stats,{2,1,{0,0}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[]},ok}}], + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}}, + + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t51}}, + {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t52}}, + {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t53}}, + {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t54}}, + {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}}, + {?eh,test_stats,{4,3,{0,0}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]}, + + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}], + + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(simple_group_case_opt) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,start_info,{1,1,2}}, + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}}, + + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t52}}, + {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t54}}, + {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}}, + {?eh,test_stats,{1,1,{0,0}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]}, + + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}], + + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(override_with_all) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,start_info,{1,1,45}}, + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + + %% TEST: {group,g1,default} + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}}, + {?eh,test_stats,{2,1,{0,0}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[]},ok}}], + + %% TEST: {group,g1,[sequence]} + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t13,{failed,{groups_spec_1_SUITE,t12}}}}, + {?eh,test_stats,{3,2,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]},ok}}], + + %% TEST: {group,g1,[parallel],[]} + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t11}}, + {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t12}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t13}}, + {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}}, + {?eh,test_stats,{5,3,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]},ok}}]}, + + %% TEST: {group,g2,[],[]} + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}}, + {?eh,test_stats,{6,3,{0,1}}}, + + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t31}}, + {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t32}}, + {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t33}}, + {?eh,tc_done,{groups_spec_1_SUITE,t33,ok}}, + {?eh,test_stats,{8,4,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]},ok}}]}, + + {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}}, + {?eh,test_stats,{8,5,{0,1}}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}}, + {?eh,test_stats,{9,5,{0,1}}}, + + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t51}}, + {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t52}}, + {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t53}}, + {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t54}}, + {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}}, + {?eh,test_stats,{11,7,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]}, + + {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}}, + {?eh,test_stats,{11,8,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}}, + {?eh,test_stats,{12,8,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}], + + %% TEST: {group,g2,default,[{g3,[sequence]}]} + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}}, + {?eh,test_stats,{13,8,{0,1}}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}}, + {?eh,test_stats,{14,9,{0,2}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t41,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t51,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t52,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t42,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t23,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,test_stats,{14,10,{0,9}}}, + + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}], + + %% TEST: {group,g2,[],[{g4,[sequence],[{g5,[sequence]}]},{g3,[sequence]}]} + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}}, + {?eh,test_stats,{15,10,{0,9}}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}}, + {?eh,test_stats,{16,11,{0,10}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}}, + {?eh,test_stats,{16,12,{0,10}}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}}, + {?eh,test_stats,{17,12,{0,10}}}, + + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t52}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t52}}}}, + {?eh,test_stats,{18,13,{0,12}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}}, + {?eh,test_stats,{18,14,{0,12}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}}, + {?eh,test_stats,{19,14,{0,12}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}], + + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]; + +test_events(override_with_spec) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,start_info,{7,4,49}}, + + %% TEST: {groups, dir, groups_spec_1_SUITE, {g1,default}}. + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}}, + {?eh,test_stats,{2,1,{0,0}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + + %% TEST: {groups, dir, groups_spec_1_SUITE, [{g1,[sequence]}, + %% {g1,[parallel],[]}]}. + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t13,{failed,{groups_spec_1_SUITE,t12}}}}, + {?eh,test_stats,{3,2,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]},ok}}], + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t11}}, + {?eh,tc_done,{groups_spec_1_SUITE,t11,ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t12}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t13}}, + {?eh,tc_done,{groups_spec_1_SUITE,t13,ok}}, + {?eh,test_stats,{5,3,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[parallel]},ok}}]}, + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + + %% TEST: {groups, dir, groups_spec_1_SUITE, {g2,[],[]}}. + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t21}}, + {?eh,test_stats,{6,3,{0,1}}}, + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t31}}, + {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t32}}, + {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t33}}, + {?eh,tc_done,{groups_spec_1_SUITE,t33,ok}}, + {?eh,test_stats,{8,4,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[parallel]},ok}}]}, + {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}}, + {?eh,test_stats,{8,5,{0,1}}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}}, + {?eh,test_stats,{9,5,{0,1}}}, + {parallel, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[parallel]},ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t51}}, + {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}}, + {?eh,tc_start,{groups_spec_1_SUITE,t52}}, + {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t53}}, + {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}}, + {?eh,tc_start,{groups_spec_1_SUITE,t54}}, + {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}}, + {?eh,test_stats,{11,7,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[parallel]},ok}}]}, + {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}}, + {?eh,test_stats,{11,8,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}}, + {?eh,test_stats,{12,8,{0,1}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + + %% TEST: {groups, dir, groups_spec_1_SUITE, {g2,default,[{g3,[sequence]}]}} + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}}, + {?eh,test_stats,{13,8,{0,1}}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}}, + {?eh,test_stats,{14,9,{0,2}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t41,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t51,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t52,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t42,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t23,{failed,{groups_spec_1_SUITE,t22}}}}, + {?eh,test_stats,{14,10,{0,9}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + + %% TEST: {groups, dir, groups_spec_1_SUITE, + %% {g2,[],[{g4,[sequence],[{g5,[sequence]}]},{g3,[sequence]}]}}. + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t21,ok}}, + {?eh,test_stats,{15,10,{0,9}}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g3,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t31,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t32,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t33,{failed,{groups_spec_1_SUITE,t32}}}}, + {?eh,test_stats,{16,11,{0,10}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g3,[sequence]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,t22,{failed,{error,crashes}}}}, + {?eh,test_stats,{16,12,{0,10}}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t41,ok}}, + {?eh,test_stats,{17,12,{0,10}}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t51,ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t52,{failed,{timetrap_timeout,2000}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t53,{failed,{groups_spec_1_SUITE,t52}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t54,{failed,{groups_spec_1_SUITE,t52}}}}, + {?eh,test_stats,{18,13,{0,12}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[sequence]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,t42,{failed,{error,crashes}}}}, + {?eh,test_stats,{18,14,{0,12}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[sequence]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,t23,ok}}, + {?eh,test_stats,{19,14,{0,12}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + + %% TEST: {groups, dir, groups_spec_1_SUITE, {g1,[sequence]}, {cases,[t12,t13]}} + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g1,[sequence]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t12,{failed,{error,crashes}}}}, + {?eh,tc_auto_skip,{groups_spec_1_SUITE,t13,{failed,{groups_spec_1_SUITE,t12}}}}, + {?eh,test_stats,{19,15,{0,13}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g1,[sequence]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + + %% TEST: {groups, dir, groups_spec_1_SUITE, {g5,[]}, {cases,[t53,t54]}} + {?eh,tc_done,{groups_spec_1_SUITE,init_per_suite,ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g2,[sequence]},ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g4,[]},ok}}, + [{?eh,tc_start,{groups_spec_1_SUITE,{init_per_group,g5,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{init_per_group,g5,[]},ok}}, + {?eh,tc_done,{groups_spec_1_SUITE,t53,{failed,{error,crashes}}}}, + {?eh,tc_done,{groups_spec_1_SUITE,t54,ok}}, + {?eh,test_stats,{20,16,{0,13}}}, + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g5,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g5,[]},ok}}], + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g4,[]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g4,[]},ok}}], + {?eh,tc_start,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]}}}, + {?eh,tc_done,{groups_spec_1_SUITE,{end_per_group,g2,[sequence]},ok}}], + {?eh,tc_done,{groups_spec_1_SUITE,end_per_suite,ok}}, + + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} + ]. + diff --git a/lib/common_test/test/ct_groups_spec_SUITE_data/groups_spec_1_SUITE.erl b/lib/common_test/test/ct_groups_spec_SUITE_data/groups_spec_1_SUITE.erl new file mode 100644 index 0000000000..ae6065bae4 --- /dev/null +++ b/lib/common_test/test/ct_groups_spec_SUITE_data/groups_spec_1_SUITE.erl @@ -0,0 +1,124 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(groups_spec_1_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +%%-------------------------------------------------------------------- +%% INFO FUNCS +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,1000}]. + +group(_) -> + [{timetrap,2000}]. + +%%-------------------------------------------------------------------- +%% CONFIG FUNCS +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = proplists:delete(name, GrProps), + ct:comment(io_lib:format("init( ~w ): ~p", [G, GrProps1])), + ct:pal("init( ~w ): ~p", [G, GrProps1]), + Config. + +end_per_group(G, Config) -> + GrProps = proplists:get_value(tc_group_properties, Config), + GrProps1 = proplists:delete(name, GrProps), + ct:comment(io_lib:format("end( ~w ): ~p", [G, GrProps1])), + ct:pal("end( ~w ): ~p", [G, GrProps1]), + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% TEST DECLARATIONS +%%-------------------------------------------------------------------- + +groups() -> + [ + {g1,[],[t11,t12,t13]}, + {g2,[sequence],[t21,{group,g3},t22,{group,g4},t23]}, + {g3,[parallel],[t31,t32,t33]}, + {g4,[],[t41,{group,g5},t42]}, + {g5,[parallel],[t51,t52,t53,t54]} + ]. + +all() -> + [ + {group,g1,default}, + {group,g1,[sequence]}, + {group,g1,[parallel],[]}, + + {group,g2,[],[]}, + {group,g2,default,[{g3,[sequence]}]}, + {group,g2,[],[{g4,[sequence],[{g5,[sequence]}]},{g3,[sequence]}]} + ]. + +%%----------------------------------------------------------------- +%% TEST CASES +%%----------------------------------------------------------------- + +t11(_) -> + ok. +t12(_) -> + exit(crashes). +t13(_) -> + ok. + +t21(_) -> + ok. +t22(_) -> + exit(crashes). +t23(_) -> + ok. + +t31(_) -> + ok. +t32(_) -> + exit(crashes). +t33(_) -> + ok. + +t41(_) -> + ok. +t42(_) -> + exit(crashes). + +t51(_) -> + ok. +t52(_) -> + ct:sleep(3000). +t53(_) -> + exit(crashes). +t54(_) -> + ok. diff --git a/lib/common_test/test/ct_groups_spec_SUITE_data/override.spec b/lib/common_test/test/ct_groups_spec_SUITE_data/override.spec new file mode 100644 index 0000000000..1bfc6405c9 --- /dev/null +++ b/lib/common_test/test/ct_groups_spec_SUITE_data/override.spec @@ -0,0 +1,15 @@ +{merge_tests,false}. + +{alias,dir,"."}. + +{groups, dir, groups_spec_1_SUITE, {g1,default}}. +{groups, dir, groups_spec_1_SUITE, [{g1,[sequence]}, + {g1,[parallel],[]}]}. + +{groups, dir, groups_spec_1_SUITE, {g2,[],[]}}. +{groups, dir, groups_spec_1_SUITE, {g2,default,[{g3,[sequence]}]}}. +{groups, dir, groups_spec_1_SUITE, {g2,[],[{g4,[sequence],[{g5,[sequence]}]}, + {g3,[sequence]}]}}. + +{groups, dir, groups_spec_1_SUITE, {g1,[sequence]}, {cases,[t12,t13]}}. +{groups, dir, groups_spec_1_SUITE, {g5,[]}, {cases,[t53,t54]}}. diff --git a/lib/common_test/test/ct_groups_test_2_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE.erl index f33be8a9d4..2392b0b850 100644 --- a/lib/common_test/test/ct_groups_test_2_SUITE.erl +++ b/lib/common_test/test/ct_groups_test_2_SUITE.erl @@ -171,18 +171,16 @@ test_events(missing_conf) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,start_info,{1,1,2}}, - {?eh,tc_start,{ct_framework,ct_init_per_group}}, - {?eh,tc_done,{ct_framework,ct_init_per_group,ok}}, - {?eh,test_stats,{1,0,{0,0}}}, + {?eh,tc_start,{ct_framework,{ct_init_per_group,group1,[]}}}, + {?eh,tc_done,{ct_framework,{ct_init_per_group,group1,[]},ok}}, {?eh,tc_start,{missing_conf_SUITE,tc1}}, {?eh,tc_done,{missing_conf_SUITE,tc1,ok}}, - {?eh,test_stats,{2,0,{0,0}}}, + {?eh,test_stats,{1,0,{0,0}}}, {?eh,tc_start,{missing_conf_SUITE,tc2}}, {?eh,tc_done,{missing_conf_SUITE,tc2,ok}}, - {?eh,test_stats,{3,0,{0,0}}}, - {?eh,tc_start,{ct_framework,ct_end_per_group}}, - {?eh,tc_done,{ct_framework,ct_end_per_group,ok}}, - {?eh,test_stats,{4,0,{0,0}}}, + {?eh,test_stats,{2,0,{0,0}}}, + {?eh,tc_start,{ct_framework,{ct_end_per_group,group1,[]}}}, + {?eh,tc_done,{ct_framework,{ct_end_per_group,group1,[]},ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]; diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl index 5c99f0f9f7..2c519f08b5 100644 --- a/lib/common_test/test/ct_hooks_SUITE.erl +++ b/lib/common_test/test/ct_hooks_SUITE.erl @@ -1046,29 +1046,34 @@ test_events(prio_cth) -> [900],[900,900],[500,900],[1000],[1200,1050], [1100],[1200]]) ++ GenPost(post_end_per_testcase, - [[1100,100],[600,200],[600,600],[600],[700],[800], - [900],[900,900],[500,900],[1000],[1200,1050], - [1100],[1200]]) ++ + lists:reverse( + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]])) ++ [{?eh,tc_done,{ct_cth_prio_SUITE,test_case,ok}}, {?eh,tc_start,{ct_cth_prio_SUITE,{end_per_group,'_',[]}}}] ++ GenPre(pre_end_per_group, - [[1100,100],[600,200],[600,600],[600],[700],[800], - [900],[900,900],[500,900],[1000],[1200,1050], - [1100],[1200]]) ++ + lists:reverse( + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]])) ++ GenPost(post_end_per_group, - [[1100,100],[600,200],[600,600],[600],[700],[800], - [900],[900,900],[500,900],[1000],[1200,1050], - [1100],[1200]]) ++ + lists:reverse( + [[1100,100],[600,200],[600,600],[600],[700],[800], + [900],[900,900],[500,900],[1000],[1200,1050], + [1100],[1200]])) ++ [{?eh,tc_done,{ct_cth_prio_SUITE,{end_per_group,'_',[]},ok}}], {?eh,tc_start,{ct_cth_prio_SUITE,end_per_suite}}] ++ GenPre(pre_end_per_suite, - [[1100,100],[600,200],[600,600],[700],[800],[900],[1000], - [1200,1050],[1100],[1200]]) ++ + lists:reverse( + [[1100,100],[600,200],[600,600],[700],[800],[900],[1000], + [1200,1050],[1100],[1200]])) ++ GenPost(post_end_per_suite, - [[1100,100],[600,200],[600,600],[700],[800],[900],[1000], - [1200,1050],[1100],[1200]]) ++ + lists:reverse( + [[1100,100],[600,200],[600,600],[700],[800],[900],[1000], + [1200,1050],[1100],[1200]])) ++ [{?eh,tc_done,{ct_cth_prio_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]}]; diff --git a/lib/common_test/test/ct_repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE.erl index 4e842bd6d6..090002d0c2 100644 --- a/lib/common_test/test/ct_repeat_1_SUITE.erl +++ b/lib/common_test/test/ct_repeat_1_SUITE.erl @@ -560,12 +560,7 @@ test_events(repeat_cs_until_any_fail) -> {repeat_1_SUITE,tc_fail_1, {failed, {error, - {{badmatch,2}, - [{repeat_1_SUITE,tc_fail_1,1}, - {test_server,my_apply,3}, - {test_server,ts_tc,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}, + {{badmatch,2},'_'}}}}}, {?eh,test_stats,{5,2,{0,0}}}, {?eh,tc_start,{repeat_1_SUITE,tc_fail_2}}, {?eh,tc_done, diff --git a/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl index fb8d31edd4..4c5b880e39 100644 --- a/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl +++ b/lib/common_test/test/ct_repeat_1_SUITE_data/repeat_1_SUITE.erl @@ -1,11 +1,21 @@ -%%%------------------------------------------------------------------- -%%% @author Peter Andersson <[email protected]> -%%% @copyright (C) 2010, Peter Andersson -%%% @doc -%%% -%%% @end -%%% Created : 11 Aug 2010 by Peter Andersson <[email protected]> -%%%------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. 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(repeat_1_SUITE). -compile(export_all). diff --git a/lib/common_test/test/ct_skip_SUITE.erl b/lib/common_test/test/ct_skip_SUITE.erl index 4ba4479208..b8be55f43a 100644 --- a/lib/common_test/test/ct_skip_SUITE.erl +++ b/lib/common_test/test/ct_skip_SUITE.erl @@ -197,7 +197,7 @@ test_events(auto_skip) -> {?eh,tc_done, {auto_skip_3_SUITE,tc1, {skipped,{failed,{auto_skip_3_SUITE,init_per_testcase, - {init_per_testcase,tc1,failed}}}}}}, + {{init_per_testcase,tc1,failed},'_'}}}}}}, {?eh,test_stats,{0,0,{0,4}}}, {?eh,tc_start,{auto_skip_3_SUITE,tc2}}, {?eh,tc_done,{auto_skip_3_SUITE,tc2,ok}}, @@ -364,12 +364,7 @@ test_events(auto_skip) -> {?eh,tc_done, {auto_skip_9_SUITE,tc8, {skipped,{failed,{auto_skip_9_SUITE,init_per_testcase, - {{badmatch,undefined}, - [{auto_skip_9_SUITE,init_per_testcase,2}, - {test_server,my_apply,3}, - {test_server,init_per_testcase,3}, - {test_server,run_test_case_eval1,6}, - {test_server,run_test_case_eval,8}]}}}}}}, + {{badmatch,undefined},'_'}}}}}}, {?eh,tc_start, {auto_skip_9_SUITE,{end_per_group,g5,[parallel]}}}, {?eh,tc_done, diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE.erl index 4471915e69..efc0309781 100644 --- a/lib/common_test/test/ct_test_server_if_1_SUITE.erl +++ b/lib/common_test/test/ct_test_server_if_1_SUITE.erl @@ -228,39 +228,39 @@ test_events(ts_if_1) -> {failed,{error,{suite0_failed,{exited,suite0_goes_boom}}}}}}, {?eh,tc_start,{ct_framework,error_in_suite}}, - {?eh,test_stats,{3,6,{3,7}}}, + {?eh,test_stats,{3,5,{4,7}}}, {?eh,tc_start,{ct_framework,error_in_suite}}, - {?eh,test_stats,{3,7,{3,7}}}, + {?eh,test_stats,{3,5,{5,7}}}, {?eh,tc_start,{ts_if_5_SUITE,init_per_suite}}, {?eh,tc_done,{ts_if_5_SUITE,init_per_suite, {skipped,{require_failed_in_suite0,{not_available,undef_variable}}}}}, {?eh,tc_auto_skip,{ts_if_5_SUITE,my_test_case, {require_failed_in_suite0,{not_available,undef_variable}}}}, - {?eh,test_stats,{3,7,{3,8}}}, + {?eh,test_stats,{3,5,{5,8}}}, {?eh,tc_auto_skip,{ts_if_5_SUITE,end_per_suite, {require_failed_in_suite0,{not_available,undef_variable}}}}, {?eh,tc_start,{ts_if_6_SUITE,tc1}}, {?eh,tc_done,{ts_if_6_SUITE,tc1,{failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}}, - {?eh,test_stats,{3,7,{4,8}}}, + {?eh,test_stats,{3,5,{6,8}}}, {?eh,tc_start,{ts_if_7_SUITE,tc1}}, {?eh,tc_done,{ts_if_7_SUITE,tc1,ok}}, - {?eh,test_stats,{4,7,{4,8}}}, + {?eh,test_stats,{4,5,{6,8}}}, {?eh,tc_start,{ts_if_8_SUITE,tc1}}, {?eh,tc_done,{ts_if_8_SUITE,tc1,{failed,{error,failed_on_purpose}}}}, - {?eh,test_stats,{4,8,{4,8}}}, + {?eh,test_stats,{4,6,{6,8}}}, {?eh,tc_user_skip,{skipped_by_spec_1_SUITE,all,"should be skipped"}}, - {?eh,test_stats,{4,8,{5,8}}}, + {?eh,test_stats,{4,6,{7,8}}}, {?eh,tc_start,{skipped_by_spec_2_SUITE,init_per_suite}}, {?eh,tc_done,{skipped_by_spec_2_SUITE,init_per_suite,ok}}, {?eh,tc_user_skip,{skipped_by_spec_2_SUITE,tc1,"should be skipped"}}, - {?eh,test_stats,{4,8,{6,8}}}, + {?eh,test_stats,{4,6,{8,8}}}, {?eh,tc_start,{skipped_by_spec_2_SUITE,end_per_suite}}, {?eh,tc_done,{skipped_by_spec_2_SUITE,end_per_suite,ok}}, diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl index 47cea190dd..06fa6ac638 100644 --- a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl +++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2010. All Rights Reserved. +%% Copyright Ericsson AB 2009-2011. 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 @@ -143,7 +143,7 @@ tc1(_) -> exit(should_have_been_skipped). tc2(_) -> - exit(should_have_been_skipped). + timeout_in_end_per_testcase. tc3(_) -> timer:sleep(5000). diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 31381abc40..6df02d12b7 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -23,8 +23,8 @@ %%% -module(ct_test_support). --include_lib("test_server/include/test_server.hrl"). -include_lib("common_test/include/ct_event.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([init_per_suite/1, init_per_suite/2, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, @@ -46,9 +46,10 @@ init_per_suite(Config) -> init_per_suite(Config, Level) -> case os:type() of {win32, _} -> - %% Extend timeout for windows as starting node + %% Extend timeout to 1 hour for windows as starting node %% can take a long time there - test_server:timetrap( 120000 * test_server:timetrap_scale_factor()); + test_server:timetrap( 60*60*1000 * + test_server:timetrap_scale_factor()); _ -> ok end, diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index f77629b4d1..2f43c1bc17 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1,3 +1 @@ -COMMON_TEST_VSN = 1.5.4 - - +COMMON_TEST_VSN = 1.6 |