aboutsummaryrefslogtreecommitdiffstats
path: root/lib/common_test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common_test')
-rw-r--r--lib/common_test/doc/src/config_file_chapter.xml241
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml3
-rwxr-xr-xlib/common_test/src/ct_config.erl4
-rwxr-xr-xlib/common_test/src/ct_config_plain.erl2
-rwxr-xr-xlib/common_test/src/ct_config_xml.erl2
-rw-r--r--lib/common_test/src/ct_run.erl10
-rw-r--r--lib/common_test/src/ct_testspec.erl4
-rw-r--r--lib/common_test/test/ct_config_SUITE_data/config/test/config_driver.erl2
-rw-r--r--lib/common_test/vsn.mk2
9 files changed, 246 insertions, 24 deletions
diff --git a/lib/common_test/doc/src/config_file_chapter.xml b/lib/common_test/doc/src/config_file_chapter.xml
index a22a5270c1..ef07ef6154 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>2009</year>
+ <year>2004</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -180,7 +180,123 @@
</section>
<section>
- <title>Examples</title>
+ <title>Using own configuration data formats</title>
+
+ <p>The nature of the configuration variables can be not only plain text
+ files with the key-value tuples, but they can be loaded from the files in
+ various formats, fetched via http from the Web, or can be loaded with help
+ of some driver process. For this purpose, mechanism of plugging in user
+ configuration handling callback modules is implemented in the Common Test.</p>
+
+ <section>
+ <title>Standard callback modules for loading configuration variables</title>
+ <p>Two callback modules for handling of configuration files are provided
+ with the Common Test application:</p>
+ <list>
+ <item>
+ <c>ct_config_plain</c> - for reading configuration files with
+ key-value tuples (traditional format). This handler will be tried to
+ parse configuration file, if no user callback is specified.
+ </item>
+ <item>
+ <c>ct_config_xml</c> - for reading configuration data from the XML
+ files.
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Using XML configuration files</title>
+
+ <p>This is an example of the XML configuration file:</p>
+
+ <pre>
+ <![CDATA[
+<config>
+ <ftp_host>
+ <ftp>"targethost"</ftp>
+ <username>"tester"</username>
+ <password>"letmein"</password>
+ </ftp_host>
+ <lm_directory>"/test/loadmodules"</lm_directory>
+</config>]]>
+ </pre>
+
+ <p>This configuration file, once read, will produce the same configuration
+ variables as the following "traditional" file:</p>
+ <pre>
+{ftp_host, [{ftp,"targethost"},
+ {username,"tester"},
+ {password,"letmein"}]}.
+
+{lm_directory, "/test/loadmodules"}.
+ </pre>
+ </section>
+
+ <section>
+ <title>Implementing of the own handler</title>
+
+ <p>Own handler can be written to handle special configuration file formats.
+ The parameter can be either file name or configuration string (empty list
+ is valid).</p>
+ <p>The callback module is completely responsible for the
+ configuration string correctness checks during runtime.</p>
+
+ <p>Callback module should have the following functions exported:</p>
+ <p>One for checking configuration parameter</p>
+
+ <p><c>Callback:check_parameter/1</c></p>
+ <p>Input value will be passed from the Common Test, as defined in the test
+ specification or given as an option to the run_test.</p>
+ <p>Return value should be any of the following value indicating if given
+ configuration parameter is valid:</p>
+ <list>
+ <item>
+ <c>{ok, {file, FileName}}</c> - parameter is a file name and
+ file exists;
+ </item>
+ <item>
+ <c>{ok, {config, ConfigString}}</c> - parameter is a config string
+ and it is correct;
+ </item>
+ <item>
+ <c>{error, {nofile, FileName}}</c> - there is no file with the given
+ name in the current directory;
+ </item>
+ <item>
+ <c>{error, {wrong_config, ConfigString}}</c> - configuration string
+ is wrong.
+ </item>
+ </list>
+
+ <p>And second function performs reading of the configuration variables:</p>
+ <p><c>Callback:read_config/1</c></p>
+ <p>Input value is the same as for <c>check_parameter/1</c> function</p>
+ <p>Return value should be either:</p>
+
+ <list>
+ <item>
+ <c>{ok, Config}</c> - is configuration variables read successfully;
+ </item>
+ <item>
+ <c>{error, Error, ErrorDetails}</c> - if callback module failed to
+ proceed.
+ </item>
+ </list>
+ <p>Above, the <c>Config</c> variable is the key-value list, possibly nested,
+ e.g. for the configuration files above it will be the following</p>
+
+ <pre>
+ [{ftp_host, [{ftp, "targethost"}, {username, "tester"}, {password, "letmein"}]},
+ {lm_directory, "/test/loadmodules"}]
+ </pre>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Examples of the configuration files</title>
<p>A config file for using the FTP client to access files on a remote
host could look like this:</p>
@@ -188,28 +304,33 @@
<pre>
{ftp_host, [{ftp,"targethost"},
{username,"tester"},
- {password,"letmein"}]}.
+ {password,"letmein"}]}.
{lm_directory, "/test/loadmodules"}.</pre>
+
+ <p>XML version shown in chapter above can also be used, but it should be
+ explicitly specified that <c>ct_config_xml</c> callback module is to be
+ used.</p>
+
<p>Example of how to assert that the configuration data is available and
use it for an FTP session:</p>
<pre>
init_per_testcase(ftptest, Config) ->
{ok,_} = ct_ftp:open(ftp),
- Config.
+ Config.
end_per_testcase(ftptest, _Config) ->
ct_ftp:close(ftp).
ftptest() ->
[{require,ftp,ftp_host},
- {require,lm_directory}].
+ {require,lm_directory}].
ftptest(Config) ->
- Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
+ Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
Local = filename:join(?config(priv_dir,Config), "loadmodule"),
ok = ct_ftp:recv(ftp, Remote, Local),
- ...</pre>
+ ...</pre>
<p>An example of how the above functions could be rewritten
if necessary to open multiple connections to the FTP server:</p>
@@ -217,7 +338,7 @@
init_per_testcase(ftptest, Config) ->
{ok,Handle1} = ct_ftp:open(ftp_host),
{ok,Handle2} = ct_ftp:open(ftp_host),
- [{ftp_handles,[Handle1,Handle2]} | Config].
+ [{ftp_handles,[Handle1,Handle2]} | Config].
end_per_testcase(ftptest, Config) ->
lists:foreach(fun(Handle) -> ct_ftp:close(Handle) end,
@@ -225,17 +346,115 @@
ftptest() ->
[{require,ftp_host},
- {require,lm_directory}].
+ {require,lm_directory}].
ftptest(Config) ->
- Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
+ Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
Local = filename:join(?config(priv_dir,Config), "loadmodule"),
[Handle | MoreHandles] = ?config(ftp_handles,Config),
ok = ct_ftp:recv(Handle, Remote, Local),
- ...</pre>
+ ...</pre>
</section>
+ <section>
+ <title>Example of own configuration handler</title>
+ <p>Simple configuration hanling "driver" can be implemented this way:</p>
+ <pre>
+-module(config_driver).
+-export([read_config/1, check_parameter/1]).
+
+read_config(ServerName)->
+ ServerModule = list_to_atom(ServerName),
+ ServerModule:start(),
+ ServerModule:get_config().
+
+check_parameter(ServerName)->
+ ServerModule = list_to_atom(ServerName),
+ case code:is_loaded(ServerModule) of
+ {file, _}->
+ {ok, {config, ServerName}};
+ false->
+ case code:load_file(ServerModule) of
+ {module, ServerModule}->
+ {ok, {config, ServerName}};
+ {error, nofile}->
+ {error, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
+ end
+ end.
+ </pre>
+ <p>Configuration string for this driver may be "config_server", if the
+ config_server.erl module below is built and is exist in the code path:</p>
+ <pre>
+-module(config_server).
+-export([start/0, stop/0, init/1, get_config/0, loop/0]).
+
+-define(REGISTERED_NAME, ct_test_config_server).
+-define(vsn, 0.1).
+
+start()->
+ case whereis(?REGISTERED_NAME) of
+ undefined->
+ spawn(?MODULE, init, [?REGISTERED_NAME]),
+ wait();
+ _Pid->
+ ok
+ end,
+ ?REGISTERED_NAME.
+
+init(Name)->
+ register(Name, self()),
+ loop().
+
+get_config()->
+ call(self(), get_config).
+
+stop()->
+ call(self(), stop).
+
+call(Client, Request)->
+ case whereis(?REGISTERED_NAME) of
+ undefined->
+ {error, not_started, Request};
+ Pid->
+ Pid ! {Client, Request},
+ receive
+ Reply->
+ {ok, Reply}
+ after 4000->
+ {error, timeout, Request}
+ end
+ end.
+
+loop()->
+ receive
+ {Pid, stop}->
+ Pid ! ok;
+ {Pid, get_config}->
+ {D,T} = erlang:localtime(),
+ Pid !
+ [{localtime, [{date, D}, {time, T}]},
+ {node, erlang:node()},
+ {now, erlang:now()},
+ {config_server_pid, self()},
+ {config_server_vsn, ?vsn}],
+ ?MODULE:loop()
+ end.
+
+wait()->
+ case whereis(?REGISTERED_NAME) of
+ undefined->
+ wait();
+ _Pid->
+ ok
+ end.
+ </pre>
+ <p>There two modules provide the ability to dynamically reload configuration
+ variables. If the <c>ct:reload_config(localtime)</c> is called from the test
+ case, all variables which were loaded with the config_driver above, will be
+ updated with the new values.</p>
+ </section>
+
</chapter>
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index d731d18783..b7e9ab88e3 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -111,11 +111,14 @@
<item><c><![CDATA[run_test -config <configfilenames> -dir <dirs>]]></c></item>
<item><c><![CDATA[run_test -config <configfilenames> -suite <suiteswithfullpath>]]></c>
</item>
+ <item><c><![CDATA[run_test -userconfig <callbackmodulename> <configfilenames> -suite <suiteswithfullpath>]]></c>
+ </item>
<item><c><![CDATA[run_test -config <configfilenames> -suite <suitewithfullpath>
-group <groupnames> -case <casenames>]]></c></item>
</list>
<p>Examples:</p>
<p><c>$ run_test -config $CFGS/sys1.cfg $CFGS/sys2.cfg -dir $SYS1_TEST $SYS2_TEST</c></p>
+ <p><c>$ run_test -userconfig ct_config_xml $CFGS/sys1.xml $CFGS/sys2.xml -dir $SYS1_TEST $SYS2_TEST</c></p>
<p><c>$ run_test -suite $SYS1_TEST/setup_SUITE $SYS2_TEST/config_SUITE</c></p>
<p><c>$ run_test -suite $SYS1_TEST/setup_SUITE -case start stop</c></p>
<p><c>$ run_test -suite $SYS1_TEST/setup_SUITE -group installation -case start stop</c></p>
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index 4b99d8db88..5623b80592 100755
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -685,7 +685,7 @@ check_callback_load(Callback)->
end.
check_config_files(Configs)->
- lists:keysearch(nok, 1,
+ lists:keysearch(error, 1,
lists:flatten(
lists:map(fun({Callback, Files})->
case check_callback_load(Callback) of
@@ -695,7 +695,7 @@ check_config_files(Configs)->
end,
Files);
{error, _}->
- {nok, {callback, Callback}}
+ {error, {callback, Callback}}
end
end,
Configs))).
diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl
index 327fc66b40..0fed58e45a 100755
--- a/lib/common_test/src/ct_config_plain.erl
+++ b/lib/common_test/src/ct_config_plain.erl
@@ -71,7 +71,7 @@ check_parameter(File)->
true->
{ok, {file, File}};
false->
- {nok, {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 e14bb0f9f9..111d1426c9 100755
--- a/lib/common_test/src/ct_config_xml.erl
+++ b/lib/common_test/src/ct_config_xml.erl
@@ -42,7 +42,7 @@ check_parameter(File)->
true->
{ok, {file, File}};
false->
- {nok, {nofile, File}}
+ {error, {nofile, File}}
end.
% actual reading of the config
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 0e7da60821..92c2334a80 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -245,11 +245,11 @@ check_and_install_configfiles(Configs, LogDir, EvHandlers) ->
false->
install([{config,Configs},
{event_handler,EvHandlers}], LogDir);
- {value, {nok, {nofile, File}}} ->
+ {value, {error, {nofile, File}}} ->
{error,{cant_read_config_file,File}};
- {value, {nok, {wrong_config, Message}}}->
+ {value, {error, {wrong_config, Message}}}->
{error,{wrong_config, Message}};
- {value, {nok, {callback, File}}} ->
+ {value, {error, {callback, File}}} ->
{error,{cant_load_callback_module,File}}
end.
@@ -702,9 +702,9 @@ check_config_file(Callback, File)->
?abs(File);
{ok, {config, _}}->
File;
- {nok, {wrong_config, Message}}->
+ {error, {wrong_config, Message}}->
exit({wrong_config, {Callback, Message}});
- {nok, {nofile, File}}->
+ {error, {nofile, File}}->
exit({no_such_file, ?abs(File)})
end.
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index ea30ccc13b..5248a6e319 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -321,9 +321,9 @@ get_absfile(Callback, FullName,#testspec{spec_dir=SpecDir}) ->
filename:join(Dir,File);
{ok, {config, FullName}}->
FullName;
- {nok, {nofile, FullName}}->
+ {error, {nofile, FullName}}->
FullName;
- {nok, {wrong_config, FullName}}->
+ {error, {wrong_config, FullName}}->
FullName
end.
diff --git a/lib/common_test/test/ct_config_SUITE_data/config/test/config_driver.erl b/lib/common_test/test/ct_config_SUITE_data/config/test/config_driver.erl
index 670639f7c7..073cb66ac2 100644
--- a/lib/common_test/test/ct_config_SUITE_data/config/test/config_driver.erl
+++ b/lib/common_test/test/ct_config_SUITE_data/config/test/config_driver.erl
@@ -41,6 +41,6 @@ check_parameter(ServerName)->
{module, ServerModule}->
{ok, {config, ServerName}};
{error, nofile}->
- {nok, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
+ {error, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
end
end.
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index cdb8e1f71c..2947c6a152 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1,3 +1,3 @@
-COMMON_TEST_VSN = 1.4.8
+COMMON_TEST_VSN = 1.5