~ubuntu-branches/ubuntu/trusty/erlang/trusty

« back to all changes in this revision

Viewing changes to lib/common_test/doc/src/config_file_chapter.xml

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
<chapter>
5
5
  <header>
6
6
    <copyright>
7
 
      <year>2004</year><year>2009</year>
 
7
      <year>2004</year><year>2010</year>
8
8
      <holder>Ericsson AB. All Rights Reserved.</holder>
9
9
    </copyright>
10
10
    <legalnotice>
13
13
      compliance with the License. You should have received a copy of the
14
14
      Erlang Public License along with this software. If not, it can be
15
15
      retrieved online at http://www.erlang.org/.
16
 
    
 
16
 
17
17
      Software distributed under the License is distributed on an "AS IS"
18
18
      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
19
19
      the License for the specific language governing rights and limitations
20
20
      under the License.
21
 
    
 
21
 
22
22
    </legalnotice>
23
23
 
24
 
    <title>Config Files</title>
 
24
    <title>External Configuration Data</title>
25
25
    <prepared>Siri Hansen, Peter Andersson</prepared>
26
26
    <docno></docno>
27
27
    <date></date>
32
32
  <section>
33
33
    <title>General</title>
34
34
 
35
 
    <p>The Common Test framework uses configuration files to
36
 
    describe data related to a test and/or an SUT (System Under Test). 
37
 
    The configuration data makes it possible to change properties without 
38
 
    changing the test program itself. Configuration data can for example be:</p>
 
35
    <p>To avoid hard coding data values related to the test and/or SUT (System
 
36
    Under Test) in the test suites, the data may instead be specified by means
 
37
    of configuration files or strings that Common Test reads before
 
38
    the start of a test run. External configuration data makes it possible to
 
39
    change test properties without having to modify the actual test suites
 
40
    using the data. Examples of configuration data:</p>
39
41
 
40
42
    <list>
41
43
      <item>Addresses to the test plant or other instruments</item>
42
 
      <item>Filenames for files needed by the test</item>
43
 
      <item>Program names for programs that shall be run by the test</item>
44
 
      <item>Any other variable that is needed by the test</item>
 
44
      <item>User login information</item>
 
45
      <item>Names of files needed by the test</item>
 
46
      <item>Names of programs that should be executed during the test</item>
 
47
      <item>Any other variable needed by the test</item>
45
48
    </list>
46
49
 
47
50
  </section>
51
54
 
52
55
    <p>A configuration file can contain any number of elements of the type:</p>
53
56
    <pre>
54
 
      {Key,Value}.</pre>
 
57
      {CfgVarName,Value}.</pre>
55
58
 
56
59
    <p>where</p>
57
60
    <pre>
58
 
      Key = atom()
59
 
      Value = term() | [{Key,Value}]</pre>
 
61
      CfgVarName = atom()
 
62
      Value = term() | [{CfgVarName,Value}]</pre>
60
63
 
61
64
  </section>
62
65
 
65
68
    <marker id="require_config_data"></marker>
66
69
 
67
70
    <p>In a test suite, one must <em>require</em> that a configuration 
68
 
    variable exists before attempting to read the associated 
69
 
    value in a test case.</p>
 
71
    variable (<c>CfgVarName</c> in the definition above) exists before
 
72
    attempting to read the associated value in a test case or config function.</p>
70
73
 
71
74
    <p><c>require</c> is an assert statement that can be part of the <seealso
72
75
    marker="write_test_chapter#suite">test suite info function</seealso> or
83
86
 
84
87
    <p>A <c>require</c> statement in the test suite info- or test case 
85
88
    info-list should look like this:
86
 
    <c>{require,Required}</c> or <c>{require,Name,Required}</c>. The
87
 
    arguments <c>Name</c> and <c>Required</c> are the same as the
 
89
    <c>{require,CfgVarName}</c> or <c>{require,AliasName,CfgVarName}</c>.
 
90
    The arguments <c>AliasName</c> and <c>CfgVarName</c> are the same as the
88
91
    arguments to <c>ct:require/[1,2]</c> which are described in the
89
92
    reference manual for <seealso marker="ct">ct</seealso>.
90
 
    <c>Name</c> becomes an alias for the configuration variable
91
 
    <c>Required</c>, and can be used as reference to the configuration
92
 
    data value. The configuration variable may be associated with an
 
93
    <c>AliasName</c> becomes an alias for the configuration variable,
 
94
    and can be used as reference to the configuration data value.
 
95
    The configuration variable may be associated with an
93
96
    arbitrary number of alias names, but each name must be unique within
94
97
    the same test suite. There are two main uses for alias names:</p>
95
98
    <list>
180
183
  </section>
181
184
 
182
185
  <section>
183
 
    <title>Examples</title>
 
186
    <title>User specific configuration data formats</title>
 
187
 
 
188
    <p>It is possible for the user to specify configuration data on a
 
189
      different format than key-value tuples in a text file, as described
 
190
      so far. The data can e.g. be read from arbitrary files, fetched from
 
191
      the web over http, or requested from a user specific process.
 
192
      To support this, Common Test provides a callback module plugin
 
193
      mechanism to handle configuration data.</p>
 
194
 
 
195
    <section>
 
196
      <title>Default callback modules for handling configuration data</title>
 
197
      <p>The Common Test application includes default callback modules
 
198
        for handling configuration data specified in standard config files
 
199
        (see above) and in xml files:</p>
 
200
      <list>
 
201
        <item>
 
202
          <c>ct_config_plain</c> - for reading configuration files with
 
203
          key-value tuples (standard format). This handler will be used to
 
204
          parse configuration files if no user callback is specified.
 
205
        </item>
 
206
        <item>
 
207
          <c>ct_config_xml</c> - for reading configuration data from XML
 
208
          files.
 
209
        </item>
 
210
      </list>
 
211
    </section>
 
212
 
 
213
    <section>
 
214
      <title>Using XML configuration files</title>
 
215
      <p>This is an example of an XML configuration file:</p>
 
216
      <pre><![CDATA[
 
217
<config>
 
218
    <ftp_host>
 
219
        <ftp>"targethost"</ftp>
 
220
        <username>"tester"</username>
 
221
        <password>"letmein"</password>
 
222
    </ftp_host>
 
223
    <lm_directory>"/test/loadmodules"</lm_directory>
 
224
</config>]]></pre>
 
225
 
 
226
      <p>This configuration file, once read, will produce the same configuration
 
227
      variables as the following text file:</p>
 
228
      <pre>
 
229
{ftp_host, [{ftp,"targethost"},
 
230
            {username,"tester"},
 
231
            {password,"letmein"}]}.
 
232
 
 
233
{lm_directory, "/test/loadmodules"}.</pre>
 
234
    </section>
 
235
 
 
236
    <section>
 
237
      <title>How to implement a user specific handler</title>
 
238
 
 
239
      <p>The user specific handler can be written to handle special
 
240
        configuration file formats. The parameter can be either file
 
241
        name(s) or configuration string(s) (the empty list is valid).</p>
 
242
 
 
243
      <p>The callback module implementing the handler is responsible for
 
244
        checking correctness of configuration strings.</p>
 
245
 
 
246
      <p>To perform validation of the configuration strings, the callback module
 
247
        should have the following function exported:</p>
 
248
 
 
249
      <p><c>Callback:check_parameter/1</c></p>
 
250
      <p>The input argument will be passed from Common Test, as defined in the test
 
251
        specification or given as an option to <c>ct_run</c> or <c>ct:run_test</c>.</p>
 
252
 
 
253
      <p>The return value should be any of the following values indicating if given
 
254
        configuration parameter is valid:</p>
 
255
      <list>
 
256
        <item>
 
257
          <c>{ok, {file, FileName}}</c> - parameter is a file name and
 
258
          the file exists,
 
259
        </item>
 
260
        <item>
 
261
          <c>{ok, {config, ConfigString}}</c> - parameter is a config string
 
262
          and it is correct,
 
263
        </item>
 
264
        <item>
 
265
          <c>{error, {nofile, FileName}}</c> - there is no file with the given
 
266
          name in the current directory,
 
267
        </item>
 
268
        <item>
 
269
          <c>{error, {wrong_config, ConfigString}}</c> - the configuration string
 
270
          is wrong.
 
271
        </item>
 
272
      </list>
 
273
 
 
274
      <p>To perform reading of configuration data - initially before the tests
 
275
        start, or as a result of data being reloaded during test execution -
 
276
        the following function should be exported from the callback module:</p>
 
277
 
 
278
      <p><c>Callback:read_config/1</c></p>
 
279
 
 
280
      <p>The input argument is the same as for the <c>check_parameter/1</c> function.</p>
 
281
      <p>The return value should be either:</p>
 
282
 
 
283
      <list>
 
284
        <item>
 
285
          <c>{ok, Config}</c> - if the configuration variables are read successfully,
 
286
        </item>
 
287
        <item>
 
288
          <c>{error, Error, ErrorDetails}</c> - if the callback module fails to
 
289
          proceed with the given configuration parameters.
 
290
        </item>
 
291
      </list>
 
292
      <p><c>Config</c> is the proper Erlang key-value list, with possible
 
293
        key-value sublists as values, like for the configuration file
 
294
        example above:</p>
 
295
 
 
296
      <pre>
 
297
        [{ftp_host, [{ftp, "targethost"}, {username, "tester"}, {password, "letmein"}]},
 
298
        {lm_directory, "/test/loadmodules"}]</pre>
 
299
 
 
300
    </section>
 
301
 
 
302
  </section>
 
303
 
 
304
  <section>
 
305
    <title>Examples of configuration data handling</title>
184
306
 
185
307
    <p>A config file for using the FTP client to access files on a remote
186
308
      host could look like this:</p>
188
310
    <pre>
189
311
    {ftp_host, [{ftp,"targethost"},
190
312
                {username,"tester"},
191
 
                {password,"letmein"}]}.
 
313
                {password,"letmein"}]}.
192
314
 
193
315
    {lm_directory, "/test/loadmodules"}.</pre>
194
 
    <p>Example of how to assert that the configuration data is available and 
 
316
 
 
317
    <p>The XML version shown in the chapter above can also be used, but it should be
 
318
    explicitly specified that the <c>ct_config_xml</c> callback module is to be
 
319
    used by Common Test.</p>
 
320
 
 
321
    <p>Example of how to assert that the configuration data is available and
195
322
      use it for an FTP session:</p>
196
323
    <pre>
197
324
    init_per_testcase(ftptest, Config) ->
198
325
        {ok,_} = ct_ftp:open(ftp),
199
 
        Config.
 
326
        Config.
200
327
 
201
328
    end_per_testcase(ftptest, _Config) ->
202
329
        ct_ftp:close(ftp).
203
330
 
204
331
    ftptest() ->
205
332
        [{require,ftp,ftp_host},
206
 
         {require,lm_directory}].
 
333
         {require,lm_directory}].
207
334
 
208
335
    ftptest(Config) ->
209
 
        Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
 
336
        Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
210
337
        Local = filename:join(?config(priv_dir,Config), "loadmodule"),
211
338
        ok = ct_ftp:recv(ftp, Remote, Local),
212
 
        ...</pre>
 
339
        ...</pre>
213
340
    
214
341
    <p>An example of how the above functions could be rewritten
215
342
      if necessary to open multiple connections to the FTP server:</p>
217
344
    init_per_testcase(ftptest, Config) ->
218
345
        {ok,Handle1} = ct_ftp:open(ftp_host),
219
346
        {ok,Handle2} = ct_ftp:open(ftp_host),
220
 
        [{ftp_handles,[Handle1,Handle2]} | Config].
 
347
        [{ftp_handles,[Handle1,Handle2]} | Config].
221
348
 
222
349
    end_per_testcase(ftptest, Config) ->
223
350
        lists:foreach(fun(Handle) -> ct_ftp:close(Handle) end, 
225
352
 
226
353
    ftptest() ->
227
354
        [{require,ftp_host},
228
 
         {require,lm_directory}].
 
355
         {require,lm_directory}].
229
356
 
230
357
    ftptest(Config) ->
231
 
        Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
 
358
        Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
232
359
        Local = filename:join(?config(priv_dir,Config), "loadmodule"),
233
360
        [Handle | MoreHandles] = ?config(ftp_handles,Config),
234
361
        ok = ct_ftp:recv(Handle, Remote, Local),
235
 
        ...</pre>
 
362
        ...</pre>
236
363
      
237
364
  </section>
238
365
 
 
366
  <section>
 
367
    <title>Example of user specific configuration handler</title>
 
368
    <p>A simple configuration handling driver which will ask an external server for
 
369
      configuration data can be implemented this way:</p>
 
370
    <pre>
 
371
-module(config_driver).
 
372
-export([read_config/1, check_parameter/1]).
 
373
 
 
374
read_config(ServerName)->
 
375
    ServerModule = list_to_atom(ServerName),
 
376
    ServerModule:start(),
 
377
    ServerModule:get_config().
 
378
 
 
379
check_parameter(ServerName)->
 
380
    ServerModule = list_to_atom(ServerName),
 
381
    case code:is_loaded(ServerModule) of
 
382
        {file, _}->
 
383
            {ok, {config, ServerName}};
 
384
        false->
 
385
            case code:load_file(ServerModule) of
 
386
                {module, ServerModule}->
 
387
                    {ok, {config, ServerName}};
 
388
                {error, nofile}->
 
389
                    {error, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
 
390
            end
 
391
    end.</pre>
 
392
 
 
393
    <p>The configuration string for this driver may be "config_server", if the
 
394
      config_server.erl module below is compiled and exists in the code path
 
395
      during test execution:</p>
 
396
    <pre>
 
397
-module(config_server).
 
398
-export([start/0, stop/0, init/1, get_config/0, loop/0]).
 
399
 
 
400
-define(REGISTERED_NAME, ct_test_config_server).
 
401
 
 
402
start()->
 
403
    case whereis(?REGISTERED_NAME) of
 
404
        undefined->
 
405
            spawn(?MODULE, init, [?REGISTERED_NAME]),
 
406
            wait();
 
407
        _Pid->
 
408
        ok
 
409
    end,
 
410
    ?REGISTERED_NAME.
 
411
 
 
412
init(Name)->
 
413
    register(Name, self()),
 
414
    loop().
 
415
 
 
416
get_config()->
 
417
    call(self(), get_config).
 
418
 
 
419
stop()->
 
420
    call(self(), stop).
 
421
 
 
422
call(Client, Request)->
 
423
    case whereis(?REGISTERED_NAME) of
 
424
        undefined->
 
425
            {error, not_started, Request};
 
426
        Pid->
 
427
            Pid ! {Client, Request},
 
428
            receive
 
429
                Reply->
 
430
                    {ok, Reply}
 
431
            after 4000->
 
432
                {error, timeout, Request}
 
433
            end
 
434
    end.
 
435
 
 
436
loop()->
 
437
    receive
 
438
        {Pid, stop}->
 
439
            Pid ! ok;
 
440
        {Pid, get_config}->
 
441
            {D,T} = erlang:localtime(),
 
442
            Pid !
 
443
                [{localtime, [{date, D}, {time, T}]},
 
444
                 {node, erlang:node()},
 
445
                 {now, erlang:now()},
 
446
                 {config_server_pid, self()},
 
447
                 {config_server_vsn, ?vsn}],
 
448
            ?MODULE:loop()
 
449
    end.
 
450
 
 
451
wait()->
 
452
    case whereis(?REGISTERED_NAME) of
 
453
        undefined->
 
454
            wait();
 
455
        _Pid->
 
456
            ok
 
457
    end.</pre>
 
458
 
 
459
    <p>In this example, the handler also provides the ability to dynamically reload
 
460
      configuration variables. If <c>ct:reload_config(localtime)</c> is called from
 
461
      the test case function, all variables loaded with <c>config_driver:read_config/1</c>
 
462
      will be updated with their latest values, and the new value for variable
 
463
      <c>localtime</c> will be returned.</p>
 
464
  </section>
 
465
 
239
466
</chapter>
240
467
 
241
468