MIN Test Framework Reference Guide


Next: , Previous: (dir), Up: (dir)

General Introduction

This page documents MIN Test Framework

Copyright © 2008 Nokia

Document Version 1.3

Online copy of this document (recent): http://min.sourceforge.net/doc/min-reference.html

Documentation download page: https://garage.maemo.org/docman/?group_id=853

Project home page: http://garage.maemo.org/projects/min/


Next: , Previous: Top, Up: Top

Short Contents

Table of Contents


Next: , Previous: Table of contents, Up: Top

Document Version History

Version Date Status Comments
1.0 17.12.2008 Draft Initial draft
1.1 20.01.2009 Draft Added chapter describing C++ modules
1.2 01.02.2009 Draft TeXinfo version draft
1.3 24.02.2009 Draft Complete TeXinfo version


Next: , Previous: Document Version, Up: Top

1 Document control


Next: , Previous: Document control, Up: Document control

1.1 Documentation conventions

Code, commandline input and output is written with the fixed-width font.


Next: , Previous: Documentation conventions, Up: Document control

1.2 Abbreviations and definitions

DLL
Dynamic Link Library
CUI
Console User Interface
IPC
Inter-Process Communication, a set of techniques for the exchange of data among two or more processes.
MIN Console UI
The Console application of MIN Test Framework.
MIN Logger
A utility of MIN Test Framework that offers logging services.
MIN Parser
A utility, which extracts information from text files.
MIN
MIN Test Framework
The name of the developed MIN Test Framework test tool.
MIN Qt
MIN Qt Graphical User Interface.
Test Case
A unique test, which either passes or fails.
Test Engine
A module of MIN Test Framework.
Test module
Contains test cases. (A test module type can be, for example, hard-coded.)
Test Module Template Wizard
A tool of MIN for automatically creating a test module template (e.g. MINUnit.)
TMC
Test Module Controller
Test Set
A collection of test cases, currently this is implemented in MIN Console UI.


Next: , Previous: Abbreviations and definitions, Up: Top

2 Using MIN for test cases implementation

This chapter describes how MIN can be used for implementing test cases.

A test module contains the actual test case implementation. Test modules are implemented as separate libraries that MIN dynamically loads. Test modules can be freely implemented, as long as they implement the test module API. Test module can be Hardcoded, normal or MINUnit. These test module types can be seen in figure below.

MIN test module types

Test modules are indicated with bolded font.


Next: , Previous: Using MIN for test cases implementation, Up: Using MIN for test cases implementation

2.1 Test Module API

Test Module API is a user-friendly API for test case execution

A test module has to provide the following interfaces to MIN:

These features are provided by the Test Module API that the test module has to implement in order fulfill MIN test module requirements.

In addition, there are some optional features that are offered by the MIN services API. MIN Services is interface from the test module to MIN Engine. For example, the interface offers UI independent printing functions, which can be used to show the test case progress on the screen, if there is a screen available (e.g. the console screen with the MIN Console UI application).


Next: , Previous: Test Module API, Up: Test Module API

2.1.1 tm_get_test_cases

The tm_get_test_cases function is used to query test cases from a test module. The test case file is provided as a parameter (optional). This method is called for every test case file separately


Next: , Previous: tm_get_test_cases, Up: Test Module API

2.1.2 tm_run_test_case

The tm_run_test_case function is used to execute a specified test case. The test case file is provided as a parameter (optional). The method returns the result of the executed test case.


Next: , Previous: tm_run_test_case, Up: Test Module API

2.1.3 tm_initialize

The tm_initialize function is called once, when the test module is loaded. Function does not take arguments and does not return any results. It is not mandatory to implement it.


Next: , Previous: tm_initialize, Up: Test Module API

2.1.4 tm_finalize

The tm_finalize function is called once when module is closed. Function does not take any arguments and does not return results. It is not mandatory to implement it.


Next: , Previous: tm_finalize, Up: Using MIN for test cases implementation

2.2 Test Module API features

The API functions provided to the test module provides optional features to the test module:


Next: , Previous: Test Module API features, Up: Test Module API features

2.2.1 tm_printf

The printing mechanism is based on asynchronous requests. Test process can send a printing request for TMC, which forwards request to UI.


Next: , Previous: tm_printf, Up: Using MIN for test cases implementation

2.3 Creating test module templates

Within MIN, there is a specific MIN Test Module Template Wizard for automatically creating a test module template, for example, a Hardcoded test module, based on the templates.

The test module template type can be hardcoded, normal, testclass or minunit. These test module template types can be seen in figure in Using MIN for test cases implementation. In the figure, the test module template types are indicated with cursive font. The figure does not contain detailed information for each test module; for example, the test case files are not shown. In addition to test module templates, the template wizard can be used to create test class templates used by MIN Using Test Scripter for creating scripted test cases or Lua Using LuaScripter for creating scripted test cases scripter.

MIN Test Module Template Wizard can be launched by running the createtestmodule script.

MIN Test Module Template Wizard takes the test module template, makes a new copy of it, and changes all the Test Module specific definitions (names) in the code files. MIN Test Module Template Wizard asks from the user the test module template type and name, as well as the path where the new test module template is created.

The test module template type hardcoded creates a test module template where every test case is implemented as a separate function.

The test module template type normal creates an empty test module template where the test cases are implemented under the tm_get_test_cases and tm_run_test_cases methods.

The test module template type minunit creates MINUnit type of template.

An example of the test module creation process is shown in Example below

     user@ubuntu:~$ createtestmodule
     Enter ModuleType:
     	normal = creates an empty test module.
     	hardcoded = creates test module that uses hardcoded test cases.
     	testclass = creates test class which is used with TestScripter.
     	luatestclass = creates test class which is used with LuaScripter.
     	minunit =  creates xUnit compatible test module
     	exit = Exit.
     Enter ModuleType (name/shortcut): m
     minunit module selected.
     Enter ModuleName which has to be a valid C variable name.
     Enter ModuleName (or exit): minunitexample
     Enter path [default is home directory ~] (or exit):
     Create test module of type m with name minunitexample to ~/
     Starting module creation to /home/user/minunitexample/
     Processing .
     Processing Makefile.am.build
     Processing createminunitmodule
     Processing ChangeLog
     Processing NEWS
     Processing autogen.sh
     Processing build.sh
     Processing AUTHORS
     Processing README
     Processing configure.ac
     Processing Makefile.am.dpkg
     Processing src
     Processing MINUnitXXX.c
     Processing MINUnitXXXCases.c
     Processing MINUnitXXX.h
     Processing data
     Processing MINUnitXXX.min.conf
     Processing debian
     Processing rules
     Processing postinst
     Processing control
     Processing changelog
     Processing install
     Processing copyright
     Processing compat
     Processing postrm
     Processing prerm
     Module created to /home/user/minunitexample/

An example of compiling the recently created module is shown in below.

     maemo@maemo:/tmp/example_module$ sh build.sh

The build script defines your test library automatically to min.conf file (min.conf path is /home/<user name>/.min/). If you now start MIN newly created module should be visible on the console UI.

Another option is create debian package of the test module. This can be achieved by issuing command dpkg-buildpackage -r fakeroot on the module directory. The created debian package installs the module to /usr/lib/min and its' configuration file to /etc/min.d.


Next: , Previous: Creating test module templates, Up: Using MIN for test cases implementation

2.4 Implementing test cases for a Hardcoded test module

Implement a test case as a separate function to a <own_module_name>.c file using the following type of method:

     int test_X( TestCaseResult* tcr )

Add your new function also into int tm_get_test_cases( const char * cfg_file, DLList ** cases ) -function.

     ENTRY(*cases,"My new test case", test_X);

See also examples from min/src/test_libraries/. For example testlibrary2.c shows an example of a test module that has all the test cases implemented inside a test module.


Next: , Previous: Implementing test cases for a Hardcoded test module, Up: Using MIN for test cases implementation

2.5 Implementing test cases for a normal test module

To add new test cases to test modules that have just been created, the user must modify the functions tm_get_test_cases() and tm_run_test_case().

MIN calls the tm_get_test_cases() function to get the test cases from the test module.

MIN calls the tm_run_test_case() function to execute a test.


Next: , Previous: Implementing test cases for a normal test module, Up: Using MIN for test cases implementation

2.6 Implementing test cases for a MINUnit test module

Implement a test case as a separate function to a <own_module_name>Cases.c file using the following type of function:

     MIN_TESTDEFINE(test_dllist_create)
     {
     MIN_ASSERT_NOT_EQUALS( l, 0 );
     }

The file consists of two sections TEST_VAR_DECLARATIONS and TEST_CASES.

Variables that are common for all test cases are defined in the TEST_VAR_DECLARATIONS section.

The TEST_CASES section contains test fixtures (MIN_SETUP and MIN_TEARDOWN) and the test cases (MIN_TESTDEFINE). Code placed in the MIN_SETUP is executed for each test case before the test case execution; and MIN_TEARDOWN after each test case. The MIN_SETUP section should be used to initialize the common variables and possible startup routines. Similarly MIN_TEARDOWN can be used for clean up routines (e.g., freeing memory).

Implementation of test case itself is done by adding new MIN_TESTDEFINE section to TEST_CASES section. Name of the new test cases is defined as a parameter for the macro. Needed test case functionality must be placed in this section (apart from setup and teardown activities).

The result of each test case is determined by using of one or several MIN_ASSERT_ macros. If any of the MIN_ASSERT_ macros discovers that the test case result is other than expected, test case result will be marked as failed.


Next: , Previous: Implementing test cases for a MINUnit test module, Up: Top

3 Integrating MIN tests to build environment

Often a source package contains test cases that are built as part of the package, and can be run to verify that the software is functioning properly, after it has been built. This chapter explains how MIN could be used for this purpose.


Next: , Previous: Integrating MIN tests to build environment, Up: Integrating MIN tests to build environment

3.1 Support in Test Module Template Wizard

Makefiles for HardCoded, Normal and MINUnit test modules, created by the Test Module Template Wizard (createtestmodule), contain a make target for executing all the tests in the module with command make check.

     maemo@maemo:~/mymodule$ make check
     make  mymoduleTestModule.so
     make[1]: Entering directory `/home/maemo/mymodule'
     make[1]: `mymoduleTestModule.so' is up to date.
     make[1]: Leaving directory `/home/maemo/mymodule'
     make  check-TESTS
     make[1]: Entering directory `/home/maemo/mymodule'
     Checking for active min processes...
     Checking for active tmc processes...
     Checking for MQ left behind...
     Checking for SHM left behind...
     MIN Test Framework,  Nokia 2008, All rights reserved,
     licensed under the Gnu General Public License version 2,
     Contact: Pekka Nuotio, DG.MIN-Support@nokia.com
     
     Test case gathering...1
       2008-10-13 04:18:10
         ---------
       * Test Module /home/maemo/mymodule/mymoduleTestModule.so
         ---------
         Test Case: mymodule_1
           o Test Result: success
           o Result Desc: PASSED
           o Message    : Passed
         ---------
         Test Case: mymodule_2
           o Test Result: failure
           o Result Desc: AssertEquals failed
           o Message    : Failed
     FAIL: mymoduleTestModule.so
     ===================
     1 of 1 tests failed
     ===================
     make[1]: *** [check-TESTS] Error 1
     make[1]: Leaving directory `/home/maemo/mymodule'
     make: *** [check-am] Error 2


Next: , Previous: Support in Test Module Template Wizard, Up: Integrating MIN tests to build environment

3.2 Test modules in one directory approach

If there are many test suites to be added to the build, creating them individually with Test Module Template Wizard may be undesired, since each module is generated to own directory, and contains files that could be shared between the modules. For MINUnit a new way of creating test modules is introduced. MIN now installs from the folder min/shared a file (minunit.c), which can be used by all MINUnit modules, so that the file is compiled with a pre-processor flag stating the file containing the test cases. Example shows Makefile.am for two test modules used in this fashion.

     check_PROGRAMS = testmodulea.so testmoduleb.so
     TESTS = $(check_PROGRAMS)
     TESTS_ENVIRONMENT = min --console --execute
     
     testmodulea_so_CFLAGS = -DCASES_FILE='"a_testCases.c"'
     testmodulea_so_LDFLAGS = -shared
     testmodulea_so_SOURCES = ../shared/minunit.c
     testmodulea_so_LDADD =  -lminutils -lmintmapi -lminevent
     
     testmoduleb_so_CFLAGS = -DCASES_FILE='"b_testCases.c"'
     testmoduleb_so_LDFLAGS = -shared
     testmoduleb_so_SOURCES = ../shared/minunit.c b_test_utils.c
     testmoduleb_so_LDADD =  -lminutils -lmintmapi -lminevent

MIN package contains unit tests, that can be executed to verify operation of MIN components, by executing command make check in directory min/ after MIN has been built and installed. The traditional CHECK tests are in directory min/tests, and tests that are using MIN tool itself can be found from min/mintests.


Next: , Previous: Test modules in one directory approach, Up: Top

4 Using MIN Parser for test data parsing

This chapter contains the MIN Parser API description for guidance on how to use MIN Parser for test data parsing.

Figure below shows how MIN Parser is involved in MIN. Test Engine uses MIN Parser for parsing data from the MIN configuration file (min.conf). MIN Parser can be used when parsing test data for test modules. Test data can be included in a test module's test case file, a test module's initialization file or a buffer.

Parser in MIN


Next: , Previous: Using MIN Parser for test data parsing, Up: Using MIN Parser for test data parsing

4.1 MIN Parser API

MIN Parser is divided into three main parts: MinParser, MinSectionParser and MinItemParser (see figure below).

MIN Parser parts

MIN Parser supports hierarchical parsing for:

MIN Parser also supports INCLUDE command. See the following limitations of this feature:


Next: , Previous: MIN Parser API, Up: MIN Parser API

4.1.1 MinParser

The MinParser component functionality opens and reads test data. The purpose of MinParser is to parse a required section of the test data. The section may be a whole test data file or some part of the data file.

The main functions of MinParser are:

MinParser* mp_create(const TPtrC* path, const TPtrC* file, TCommentType comments)
Creates MinParser with path and file information.
Possible errno return values
ENOENT: invalid path argument.

EACCES: permission denied.

const TPtrC* path
The path to folder where config file located.
const TPtrC* file
The filename of config file.
TCommentType comments
Indication of the comment type.

ENoComments: Comments are included with parsing.

ECStyleComments: The user wants to parse sections without c-style comments.

Return value
MinParser struct object.
MinParser* mp_create_mem(const TPtrC* buffer, TCommentType comments)
Creating a parser with buffer information.
const TPtrC* buffer
The buffer to be parsed.
TCommentType comments
Indication of the comment type.

ENoComments: Comments are included with parsing.

ECStyleComments: The user wants to parse sections without c-style comments.

Return value
MinParser struct object.
void mp_destroy(MinParser** mp)
Destroy MinParser struct component and free allocated memory and resources.
MinParser** mp
Pointer reference to used MinParser struct component.

INITPTR pointer value is returned in mp pointer parameter if destroying operation completed successfully.

Return value
None
MinSectionParser* mp_section(MinParser *mp, const TPtrC* start_tag, const TPtrC* end_tag, int seeked)
Open and read configuration source and parses a required section. If start tag is empty the parsing starts begin of the configuration file.

If end tag is empty the parsing goes end of configuration file.

This function will parse next section after the earlier section if the sought parameter is set to 1.

If configuration file includes several sections with both start and end tags so sought parameter seeks the required section.

Possible errno return values
EINVAL: invalid value was passed to the function.
MinParser *mp
Pointer to MinParser instance.
const TPtrC* start_tag
Start tag name.

If the start tag is empty, the parsing starts at the beginning of the file.

const TPtrC* end_tag
End tag name.

If the end tag is empty, the parsing goes to the end of the file.

int seeked
Indicates the tag on which the parsing ends.
Return value
MinSectionParser struct object.
MinSectionParser* mp_next_section( MinParser *mp, const TPtrC* start_tag, const TPtrC* end_tag, int seeked)
Open and read configuration source and parses a required section. If start tag is empty the parsing starts begin of the configuration file.

If end tag is empty the parsing goes end of configuration file.

This method will parse next section after the earlier section if sought parameter is set to 1.

If configuration file includes several sections with both start and end tags so sought parameter seeks the required section.

Possible errno return values:
EINVAL: Invalid value was passed to the function.
MinParser *mp
Pointer to MinParser instance.
const TPtrC* start_tag
Start tag name.

If the start tag is empty, the parsing starts at the beginning of the file.

const TPtrC* end_tag
End tag name.

If the end tag is empty, the parsing goes to the end of the file.

int seeked
A section indicator.
Return value
MinSectionParser struct object.


Next: , Previous: MinParser, Up: MIN Parser API

4.1.2 MinSectionParser

The purpose of MinSectionParser is to parse the required lines of the section to forward operations.

The main methods of CMinSectionParser are:

MinSectionParser* msp_create(unsigned int length);
Creates a new MinSectionParser.
unsigned int length
The length of the section to be parsed.
Possible errno return values
ENOMEM: No sufficient memory to allocate new struct object.
Return value
MinSectionParser struct object.
void msp_destroy(MinSectionParser** msp)
Destroys previously created MinSectionParser.
MinSectionParser** msp
the reference pointer to MinSectionParser struct component. Returns address of MinItemParser or INITPTR in case of failure.
Possible errno values
ENOMEM: No sufficient memory to allocate new struct object.
Return value
none
MinItemParser* msp_get_item_line(MinSectionParser* msp, const TPtrC* tag, TTagToReturmValue tag_indicator)
Parses the next line for items parsing with a tag.

Returns address of MinItemParser or INITPTR in case of failure.

MinSectionParser* msp
The reference pointer to MinSectionParser struct component.
const TPtrC* tag
Indicates the tag to start with. If start tag is empty the parsing starts begin of the section.
TTagToReturmValue tag_indicator
Idicates if tag will be included to the returned object.
Return value
MinItemParser struct object or INITPTR in case of failure.
MinSectionParser* msp_get_next_item_line(MinSectionParser* msp)
Parses a next line for items parsing.
MinSectionParser* msp
MinSectionParser entity to operate on.
Return value
MinSectionParser construct object.
MinItemParser* msp_get_next_tagged_item_line(MinSectionParser* msp, const TPtrC* tag, TTagToReturnValue tag_indicator)
Parses a next line for items parsing with a tag.

Returns pointer to MinItemParser struct component.

MinSectionParser* msp
MinSectionParser entity to operate on.
const TPtrC* tag
Indicates the tag to start with. If start tag is empty the parsing starts begin of the section.
TTagToReturnValue tag_indicator
Indicates if tag will be included to the returned object.
Return value
MinItemParser struct object.
MinSectionParser* msp_sub_section(TPtrC* start_tag, TPtrC* end_tag, int seeked)
Parses a sub sections from the main section with a start and with an end tag.

Returns pointer to MinSectionParser struct component.

const TPtrC* start_tag
Indicates the tag to start on.
const TPtrC* end_tag
Indicates the tag to end on.
int seeked
The sought parameter indicates subsection that will be parsed.
Return value
MinSectionParser struct object.
MinSectionParser* msp_next_sub_section(MinSectionParser* msp, const TPtrC* start_tag, const TPtrC* end_tag, int seeked)
Parses a next subsection from the main section with a start and with an end tag.

Returns pointer of MinSectionParser or INITPTR in case of failure.

MinSectionParser* msp
MinSectionParser entity to operate on.
const TPtrC* start_tag
Indicates the tag to start on.
const TPtrC* end_tag
Indicates the tag to end on.
int seeked
The sought parameter indicates subsection that will be parsed.
Return value
MinSectionParser struct object.
MinSectionParser* msp_next_sub_section(MinSectionParser* msp, const TPtrC* start_tag, const TPtrC* end_tag, int seeked)
Parses a next subsection from the main section with a start and width an end tag.
MinSectionParser* msp
Pointer to the MinSectionParser struct component.
const TPtrC* start_tag
Pointer to start tag string.
const TPtrC* end_tag
Pointer to end tag string.
int seeked
The sought parameter indicates subsection that will be parsed.
Return value
Return pointer to MinSectionParser struct component or INITPTR pointer value in case of failure.
int msp_get_line(MinSectionParser* msp, const TPtrC* tag, TPtrC** line, TTagToReturnValue tag_indicator)
Get a line from section with a tag.
Possible errno values
EINVAL errno value when invalid value was passed as a parameter.
MinSectionParser* msp
Pointer to the MinSectionParser struct component.
const TPtrC* tag
Indicates the tag to start with. If start tag is empty the parsing starts begin of the section.
TPtrC** line
Parsed line is returned through this variable.
TTagToReturnValue tag_indicator
Indicates if tag will be included to the returned line.
Return value
Returns 0 in case of success, -1 in case of failure.
int msp_get_next_line(MinSectionParser* msp, TPtrC** line)
Parses next line.
Possible errno values
EINVAL when invalid value was passed as a parameter.
MinSectionParser* msp
Pointer to the MinSectionParser struct component.
TPtrC** line
Parsed line is returned through this variable.
Return value
Returns value 0 in case of success, -1 in case of failure.
int msp_get_next_tagged_line(MinSectionParser* msp, const TPtrC* tag, TPtrC** line, TTagToReturnValue tag_indicator)
Get next line with tag.
Possible errno values
EINVAL when invalid value was passed as a parameter.
MinSectionParser* msp
Pointer to the MinSectionParser struct component.
const TPtrC* tag
Indicates the tag to start with. If start tag is empty the parsing starts begin of the section.
TPtrC** line
Parsed line is returned through this variable. If line is no found INITPTR pointer value is returned.
TTagToReturnValue tag_indicator
Indicates if tag will be included to the return line.
Return value
Returns value 0 in case of success, -1 in case of failure.
int msp_get_position(MinSectionParser* msp)
Get current position.
Possible errno values
EINVAL when invalid value was passed as a parameter.
MinSectionParser* msp
Pointer to the MinSectionParser struct component.
Return value
Returns current parsing position, or value -1 in case of failure.
int msp_set_position(MinSectionParser* msp, unsigned int pos)
Set position. This function can be used to set parsing position, e.g. to rewind back to some old position retrieved with GetPosition.
Possible errno values
EINVAL when invalid value was passed as a parameter.
MinSectionParser* msp
Pointer to the MinSectionParser struct component.
unsigned int pos
Indicates the position to which section parser should go.
Return value
Returns error value in case of failure.
void msp_set_data(MinSectionParser* msp, const TPtrC* data, TPtrC* start_pos, unsigned int length)
Create a section.
MinSectionParser* msp
Pointer to the MinSectionParser struct component.
const TPtrC* data
String data which are to be parsed.
TPtrC* start_pos
Position from which parsing should start.
unsigned int length
Length of the data in bytes.
Return value
None
const TPtrC* msp_des(const MinSectionParser* msp)
Returns current section.
const MinSectionParser* msp
Pointer to the MinSectionParser struct component.
Return value
Return pointer to the data that parser is parsing.


Next: , Previous: MinSectionParser, Up: MIN Parser API

4.1.3 MinItemParser

The purpose of MinItemParser is to parse strings, integers and characters. The main methods of MinSectionParser are:

MinItemParser* mip_create(TPtrC* section, int start_pos, int length)
Creates MinItemParser struct component with given string data.
TPtrC* section
Pointer to section string data.
int start_pos
Start point in given section string by integer value.
int length
Length of given section string.
Return value
Pointer to created new MinItemParser struct component.
void mip_destroy(MinItemParser** msp)
Frees allocated memory of MinItemParser struct component.

Returns INITPTR if destroying operation complete successfully.

MinItemParser** msp
Pointer to MinItemParser struct component which to be destroyed.
Return value
None
int mip_parse_start_and_end_pos(MinItemParser* mip, TPtrC* start_tag, TPtrC** ref_start_pos, TPtrC** ref_end_pos, TPtrC** ref_extra end_pos)
Parses MinItemParser section and returns results with start, end and extra end positions including length of parsed part of section.

If start tag keyword is used then method searches string data after this given keyword. If start tag is not used then parsing starts at the beginning of section string.

Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* start_tag
A reference to the parsed string.
TPtrC** ref_start_pos
Reference pointer start position of parsed section part.
TPtrC** ref_end_pos
Reference pointer end position of parsed section part.
TPtrC** ref_extra end_pos
Reference pointer extra end position of parsed section. Extra end position is section string location after last quote.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_string(MinItemParser* mip, TPtrC* tag, TPrtC** string)
Gets first string according to tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Pointer to tag string for searching section part string.
TPrtC** string
Reference string pointer for parsed string result.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_next_string(MinItemParser* mip, TPtrC** string)
Gets next string according to previous section part string from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC** string
Reference string pointer for parsed result string.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_next_tagged_string(MinItemParser* mip, TPtrC* tag, TPtrC** string)
Gets next tagged string according to tag and earlier used MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Tag string for search of parsing. If tag string is empty then parsing start at the beginning of section string.
TPtrC** string
Reference string pointer for parsed result string.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_int(MinItemParser* mip, TPtrC* tag, int* value)
Gets first integer value according to tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Tag string for search of parsing. If tag string is empty then parsing starts the beginning of section string.
int* value
Reference string pointer for found integer value by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_next_int(MinItemParser* mip, init* value)
Gets next integer value according to tag and earlier used StiItemParser section sting.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
init* value
Reference string pointer for parsed result string.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_next_tagged_int(MinItemParser* mip, TPtrC* tag, int* value)
Gets next tagged integer value according to tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Tag string for search of parsing.
int* value
Reference string pointer for found integer value by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_uint(MinItemParser* mip, TPtrC* tag, unsigned int* value)
Gets first unsigned integer value according to tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Tag string for search of parsing. If tag string is empty then parsing starts at the beginning of section string.
unsigned int* value
Reference string pointer for found unsigned integer value by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_next_uint(MinItemParser* mip, unsigned int* value)
Gets next unsigned integer value according to previous parsing operation by tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
unsigned int* value
Reference string pointer for found unsigned integer value by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if operation failed.

int mip_get_next_tagged_uint(MinItemParser* mip, TPtrC* tag, unsigned int* value)
Gets next tagged unsigned integer value according to previous parsing operation by tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Tag string for search of next tagged unsigned integer data.
unsigned int* value
Reference string pointer for found unsigned integer value by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if searching operation failed.

int mip_get_char(MinItemParser* mip, TPtrC* tag, TPtrC** chr)
Gets first character by tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Tag string for search of next tagged unsigned integer data.
TPtrC** chr
Reference string pointer for found character data by parsing operation.
Return value
0 if parsing operation completed successfully.

-1 if section string length is zero.

-2 if parsing operation failed by any reason.

int mip_get_next_char(MinItemParser* mip, TPtrC** chr)
Gets next character according to previous parsing operation from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC** chr
Reference string pointer for found character data by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if next character searching failed.

int mip_get_next_tagged_char(MinItemParser* mip, TPtrC* tag, TPtrC** chr)
Gets next tagged character by tag from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC* tag
Tag string for search of next tagged unsigned integer data.
TPtrC** chr
Reference string pointer for found tagged character data by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if next character searching failed.

int mip_get_remainder(MinItemParser* mip, TPtrC** string)
Gets remainder string from MinItemParser section string.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TPtrC** string
Reference string pointer for found remainder string by parsing operation.
Return value
0 if parsing operation completed successfully

-1 if remainder string parsing failed.

int mip_set_parsing_type(MinItemParser* mip, TParsingType type)
Sets parsing type value for MinItemParser struct component.
Possible errno values
EINVAL errno value when parsing operation failed.
MinItemParser* mip
Pointer to MinItemParser struct component.
TParsingType type
New parsing type for parsing operations.
Return value
0 if parsing operation completed successfully

-1 if MinItemParser struct component not available.

TParsingType mip_get_parsing_type(MinItemParser* mip)
Gets parsing type value from MinItemParser section string.
Possible errno values
EINVAL errno value when MinItemParser struct component not available.
MinItemParser* mip
Pointer to MinItemParser struct component.
Return value
Returns parsing type value if parsing operation completed successfully

-1 if operation failed.

Note 1: ENormalParsing type parsing is takes string after tag keyword and is separated result strings by white spaces. For example, if the section string is "Tag1 Word1 Word2 Tag2 Word3 Word4 Tag3 Word5 Word6" if is used tag "Tag2" then parsed result string is "Word3" by mip_get_string() method. If after this parsing will did new parsing by mip_get_next_string() then next parsed result string is "Word4".

Note 2: EQuoteStyleParsing type parsing takes string inside of two quotes and this parsed may including also white spaces. For example, if only the start tag has been found from the section string then parsing will be returned rest of string after start tag.

Note 3: If section string including comments strings with two backslashes then parsing will be returned string after the first backslashes.


Next: , Previous: MinItemParser, Up: Top

5 Using Test Scripter for creating scripted test cases


Next: , Previous: Using Test Scripter for creating scripted test cases, Up: Using Test Scripter for creating scripted test cases

5.1 Test Scripter test case file

The Test Scripter test case file defines the commands to be executed in a test case described with a simple scripting language. The test case file may contain several test cases, the descriptions of which start with the tag [Test] and end with the tag [Endtest]. The test case is executed sequentially line by line. The test case itself is described with keywords, arguments and argument value pairs between the start and end tags. An example of a test case is described below.

     [Test]
     title Create, print, run example and delete
     createx TestScriptClass testobj
     print Call Example method
     testobj Example pa ra me ters
     print Example method called, delete instance
     delete testobj
     [Endtest]

The test case title must be given after the title keyword on the first line of the test case definition. In the example above, the create keyword creates a new instance of TestScriptClass, which is named test. The print keyword is used to print information to the UI. The fourth line of the example test case executes the Example method of the test object with four parameters: pa, ra, me and ters. The delete keyword is used to delete the test object. Test Scripter's test case file and test module initialization file may contain macro definitions used in test cases. Macros are defined inside a define section started with [Define] tag ended with [Enddefine] tag, for example:

     [Define]
     ENOERR 0
     [Enddefine]


Next: , Previous: Test Scripter test case file, Up: Using Test Scripter for creating scripted test cases

5.2 Setting up the Scripter

Test Scripter is configured for use by adding Test Scripter as a test module to MIN. The test case file is added as a test case file for Test Scripter. An example of configuring Test Scripter as a test module can be seen in example in section Configuring MIN via the MIN Test Framework initialization file.


Next: , Previous: Setting up the Scripter, Up: Using Test Scripter for creating scripted test cases

5.3 Creating a test class

A new test class can be easily created with MIN Test Module Template Wizard that comes with the MIN release

$ createtestmodule

A new test class is now created with the given name to the given path. The next step is to create the building block methods to the test class.

To create the building block methods to the test class:

  1. Implement the building blocks to /<testclassname>/src/<testclassname>Cases.c file (there is one example method, ExampleTest, that can be copy-pasted).
  2. Add entry for every method to function ts_get_test_cases (<testclassname>Cases.c):

    ENTRY(*list,"Example",ExampleTest);

  3. Add entry lines for every method to FORWARD DECLARATIONS:

    LOCAL int ExampleTest( MinItemParser* item );

  4. Build the test class from the /<testclassname>/group directory by using build.sh script. It will automatically copy test class library to /home/<user name>/.min.

    Now the test class is created. The next step is to implement test cases to test the test case file used by Test Scripter. An example test case file can be found in /<testclassname>/group/Example.CFG. The test case file is constructed using the script language defined in this document.

    Copy the test case file to /home/<user name>/.min/

    Now you should be able to execute your test class module by using console UI or EXT INTERFACE.


Next: , Previous: Creating a test class, Up: Using Test Scripter for creating scripted test cases

5.4 Accessing script variables from test class

Script local variables (See var keyword.) can be retrieved from inside the test class as well as set to different value . The functions below are available for test class to set and get variable values.

     int SetLocalValue (const char *varname, const char *varval);
     /* --------------------------------------------------------------- */
     /** Assign integer value to script variable
      * @param varname name of variable
      * @param varval value to assign
      * @return 0 on success, -1 on error
      */
     int SetLocalValueInt (const char *varname, const long value);
     /* --------------------------------------------------------------- */
     /** Get value of script variable as an integer
      * @param varname name of variable
      * @param value [out] variable value
      * @return 0 on success, -1 on error
      */
     int GetLocalValueInt (const char *varname, long *value);
     /* --------------------------------------------------------------- */
     /** Get value of script variable as a string
      * @param varname name of variable
      * @param value [out] variable value
      * @return 0 on success, -1 on error
      */
     int GetLocalValue (const char *varname, char **value);

Note that test class can only get and set local script variables, it's not possible to declare variables in the tests class.


Next: , Previous: Accessing script variables from test class, Up: Using Test Scripter for creating scripted test cases

5.5 Scripter internal variables

Scirpter holds internal variables that are available to script or test class similar to local variables. The internal variables are counters shown in and can be used, for example, to bail out from a long test loop in case some error level is reached, or to call some special clean up function in case of crashed test method calls.

Scripter internal variables
FAIL_COUNT
Number of failed method and combiner calls
CRASH_COUNT
Number of crashed method and combiner calls
TOUT_COUNT
Number of timed out method and combiner calls
ABORT_COUNT
Number of aborted method and combiner calls
ERROR_COUNT
Sum of all the of the above
TOTAL_COUNT
Total number of method and combiner calls


Next: , Previous: Scripter internal variables, Up: Using Test Scripter for creating scripted test cases

5.6 General keywords


Next: , Previous: General keywords, Up: General keywords

5.6.1 title keyword

The title keyword is used to give a verbal description for a test case. The description is placed after the keyword. The title keyword is mandatory for every test case and must be placed as the first keyword in the test case description (Test Scripter test case file). For example:

     title Create, print, run example and delete


Next: , Previous: title keyword, Up: General keywords

5.6.2 timeout keyword

The timeout keyword is used to give a timeout value for a test case. The timeout value is given as an argument for the timeout keyword, as shown below.

Argument
Timeout value
The timeout value in milliseconds.

The timeout keyword can be used, for example, in the following way (timeout 10 seconds):

     timeout 10000


Next: , Previous: timeout keyword, Up: General keywords

5.6.3 blocktimeout keyword

The blocktimeout keyword is used to give a timeout value for blocking scipter commands (for example allocate, expect, wait). The timeout value is given in seconds. Value 0 means no timeout, unless the blocking timeout is specified in test script, it defaults to 10 minutes.

Argument
Timeout value
The bloking timeout value in seconds.

The blocktimeout keyword can be used, for example, in the following way (timeout 10 seconds):

     # accept 5 minute timeout for event E
     blocktimeout 300
     wait E
     # no timeout
     blocktimeout 0


Next: , Previous: blocktimeout keyword, Up: General keywords

5.6.4 print keyword

The print keyword can be used to print, for example, progress information to the UI. The printed description is placed after the print keyword; see the example in section Test Scripter test case file


Next: , Previous: print keyword, Up: General keywords

5.6.5 var keyword

The var keyword declares a variable for the scripter. A variable can be initialized during its declaration. The value of variable can be set in script or test class. When calling methods from a test object, the declared variable can be passed as an argument to this method. If variable name appears in text used with print keyword, its value gets printed. The var keyword has one mandatory and one optional argument, described below.

Note: var keyword may be used to declare variables used in remote test case execution. See Remote test case control, expect keyword.

Argument
variable name
The variable name.
Optional argument
variable value
The value which declared variable is to be initialized.

The var keyword can be used for example in the following way:

     var variable2
     var variable1 text
     var variable2 1
     sometestobj somemethod variable1 variable2
     print variable2


Next: , Previous: var keyword, Up: Using Test Scripter for creating scripted test cases

5.7 Test Case control


Next: , Previous: Test Case control, Up: Test Case control

5.7.1 createx keyword

The createx keyword is used to create a new instance of a test class. createx has two mandatory arguments, which are described below.

Argument
Test class name
The test class name for the new object.
Test object name
The name of the created new instance of the test class.

The createx keyword can be used, for example, in the following way:

     createx TestScriptClass test


Next: , Previous: createx keyword, Up: Test Case control

5.7.2 delete keyword

The delete keyword is used to delete an instance of a test class. delete has one mandatory argument, which is described in Table below.

Argument
Test object name
The name of the instance of the test class that is deleted.

The delete keyword can be used, for example, in the following way:

     delete test


Next: , Previous: delete keyword, Up: Test Case control

5.7.3 allownextresult keyword

The allownextresult keyword is used to add valid result values for a method and for asynchronous commands. The default value for the expected result is 0, and if a value is set with allownextresult, 0 is removed from the expected values. A method may either return or leave with the specified result. Every method call removes all allowed results. That is, after every method call, the default value 0 is again the only expected result value. Either multiple allownextresult keywords can be placed before a method call or allownextresult keyword can have multiple parameters.

Argument
An error code
Error code, which is allowed from the next method. It can be custom value, or errno.

The allownextresult keyword can be used, for example, in the following way:

     allownextresult -1

The allownextresult keyword can be used, for example, in the following way:

     allownextresult -1 -2 -3 -4


Next: , Previous: allownextresult keyword, Up: Test Case control

5.7.4 allowerrorcodes keyword

The allowerrorcodes keyword is used to add valid result values for a method and for asynchronous commands. The default value for the expected result is 0, and if a value is set with allowerrorcodes, 0 is removed from the expected values. A method may either return or leave with the specified result. Every method call removes all allowed results. That is, after every method call, the default value 0 is again the only expected result value. Either multiple allowerrorcodes keywords can be placed before a method call or allowerrorcodes keyword can have multiple parameters.

Argument
An error code
Error code, which is allowed from the next method. It can be custom value, or errno.

The allowerrorcodes keyword can be used, for example, in the following way:

     allowerrorcodes -1

The allowerrorcodes keyword can be used, for example, in the following way:

     allowerrorcodes -1 -2 -3 -4


Next: , Previous: allowerrorcodes keyword, Up: Test Case control

5.7.5 sleep keyword

The sleep keyword is used to pause the execution of a test case for a specified timeout. Sleep has one mandatory argument, which is described below.

The sleep keyword only stops the test case line-runner active object for the specified period. All the other user active objects will continue to be serviced. That is, no further lines of the test case file will be executed during that delay, but the process is not halted; any user active objects may still be completed.

Argument
Timeout
The timeout for the pause, specified in milliseconds.

The sleep keyword can be used, for example, in the following way:

     sleep 10000   // pause for 10 seconds

Note: sleep keyword works in the same way as deprecated pausecombiner keyword.


Next: , Previous: sleep keyword, Up: Test Case control

5.7.6 pausecombiner keyword (DEPRECATED)

pausecombiner works in the same way as sleep keyword. See sleep keyword.


Next: , Previous: pausecombiner keyword, Up: Test Case control

5.7.7 run keyword

The run keyword is used to start a specified test case. It has several mandatory and optional arguments, described below.

Mandatory arguments
testmodule
The test module name.
configfile
The test case configuration file. If does not contain path but only filename then $HOME/.min path is used.
Test case number
The test case number to be executed from configfile.
Optional arguments
expect
The expected result default 0 = ENOERR
testid
Test case identification, which is used by other keywords to identify the test case

Note: Avoid using the same testid for many test case runs

Ini
The initialization file for test module (not supported yet)
category
The result category; either normal, leave, panic, exception or timeout
timeout
Test case timeout.
title
Test case title. If given, following rules must be held:

The run keyword can be used for example in the following way:

     run netmodule net.cfg 5 testid=test1 expect=3 ini=ini.txt
     run netmodule net.cfg -1 testid=test2 title="My test case example"


Next: , Previous: run keyword, Up: Test Case control

5.7.8 cancel keyword

The cancel keyword is used to cancel a started test case. The test case is cancelled by immediately killing the thread that executes the test case. The cancel keyword has one mandatory argument as described below.

Argument
testid
The test ID from the run command.

The cancel keyword can be used, for example, in the following way:

     cancel test1


Next: , Previous: cancel keyword, Up: Test Case control

5.7.9 pause keyword

The pause keyword is used to pause a test case. The test case is paused by stopping the process that executes the test case. The pause keyword has one mandatory and one optional argument, described below.

Mandatory argument
testid
The test ID from the run command.
Optrional argument
Time
Pause time in milliseconds. After this time, resume is called automatically (if not given, resume needs to be called explicitly).

The pause keyword can be used, for example, in the following way:

     pause test1 time=10


Next: , Previous: pause keyword, Up: Test Case control

5.7.10 resume keyword

The resume keyword is used to resume a paused test case. resume has one mandatory argument, described below.

Argument
testid
The test ID from the run command.

The resume keyword can be used for, example, in the following way:

     resume test1


Next: , Previous: resume keyword, Up: Test Case control

5.7.11 complete keyword

The complete keyword is used to have a started test case wait to complete. It blocks until the test case has finished. complete has one mandatory argument, described below.

Argument
testid
The test ID from the run command.

The complete keyword can be used, for example, in the following way:

     complete test1

Note: If this keyword is used when more than one test case has the same testid (even if it's completed already) it will wait for the last test case to complete. Avoid using the same testid for many test case runs. See run keyword.


Next: , Previous: complete keyword, Up: Test Case control

5.7.12 loop keyword

The loop keyword is used to repeat a section of the test case file for the specified number of iterations. The section to be repeated is enclosed with the loop and endloop keywords.

Argument
Loop times
The loop count, that is, the number of times that the loop is executed.
Optional argument
msec
(optional) This keyword says that "Loop times" argument stands for the time in milliseconds during which loop will be looped

The loop keyword can be used, for example, in the following way:

     loop 5
     // execute this 5 times
     print pa ra me ter
     endloop


Next: , Previous: loop keyword, Up: Test Case control

5.7.13 breakloop keyword

The breakloop keyword is used to prematurely exit the current loop. The breakloop keyword can be used, for example, in the following way:

     loop 5
     var exitcond
     someclass somemethod someparam
     if exitcond
         breakloop
     endif
     endloop


Next: , Previous: breakloop keyword, Up: Test Case control

5.7.14 endloop keyword

The endloop keyword is used to specify the end of a looped section.


Next: , Previous: endloop keyword, Up: Test Case control

5.7.15 if else and endif keywords

The if, else and endif keywords can be used for conditional execution in the script. The condition for if must be variable or value. Value 0 and string "false" (case insensitive) is interpreted as false, other values as true. If block must always be closed with endif keyword. Nesting of if-blocks is supported.

     var v
     if v
       print is true
     else
       print is false
     endif


Next: , Previous: if else and endif keywords, Up: Test Case control

5.7.16 Object name

The test object name can be considered as a temporary keyword, which is valid between its creation with the createx keyword and its deletion with the delete keyword. The object name is used to call methods from a test object. The method name is given as the first argument for the object name, and the method may have arguments, which are forwarded to the test class method. For example:

     TestObjectName MethodName <method arguments 1 2 3>.


Next: , Previous: Object name, Up: Using Test Scripter for creating scripted test cases

5.8 Event control

The keywords described in the following sections are used to control MIN Event System. For information about MIN Event System. See Using MIN Event System for test cases synchronization.


Next: , Previous: Event control, Up: Event control

5.8.1 request keyword

The request keyword is used to request an event. If someone wants to use an event, it must first be requested, and after that it can be waited. After the event is not used anymore, it must be released. The request keyword has one mandatory argument, and one optional parameter. Both are described below.

Argument
Event
The event name.
Optional argument
State
Keyword "state" must be specified if request is for event of "state" type.

The request keyword can be used, for example, in the following ways:

     request Event1
     request Event2 state


Next: , Previous: request keyword, Up: Event control

5.8.2 wait keyword

The wait keyword is used to wait for an event. A request must be called before wait, and wait blocks until the requested event is set. wait may proceed immediately if the requested event is a state event and already pending (for example, a phone call is already active). wait has one mandatory argument, which is described below.

Argument
Event
The event name.

The wait keyword can be used, for example, in the following way:

     wait Event1


Next: , Previous: wait keyword, Up: Event control

5.8.3 release keyword

The release keyword is used to release an event. Every requested event must be released explicitly when it is not used anymore. release has one mandatory argument, which is described below.

Argument
Event
The event name.

The release keyword can be used, for example, in the following way:

     release Event1


Next: , Previous: release keyword, Up: Event control

5.8.4 set keyword

The set keyword is used to set an event. Every set state event must be explicitly unset.

set has one mandatory argument and also one optional argument, as described below.

Argument
Event
The event name.
Optional argument
State
If a state is given, sets the state event, otherwise sets an indication event. A state event remains set until it is unset explicitly with the unset keyword. An indication event is set only once to every requester and implicitly unset after that.

The set keyword can be used, for example, in the following ways:

     set Event1
     set Event2 state


Next: , Previous: set keyword, Up: Event control

5.8.5 unset keyword

The unset keyword is used to unset a state event. Every set state event must be unset. Indication events cannot be unset. unset blocks until everyone who has requested the specified event has released the event. unset has one mandatory argument, which is described below.

Argument
Event
The event name.

The unset keyword can be used, for example, in the following way:

     unset Event1


Next: , Previous: unset keyword, Up: Using Test Scripter for creating scripted test cases

5.9 Remote test case control


Next: , Previous: Remote test case control, Up: Remote test case control

5.9.1 allocate keyword

The allocate keyword is used to allocate a slave, for example for running a test case on a remote phone. It uses Remote Control Protocol (RPC). The slave must always be allocated first before it can be used. The allocate keyword has two mandatory arguments, described below.

Argument
Slave type
The type of the slave

MIN only supports slave phone. phone indicates that slave phone is also running MIN. Other types must be handled by the slave implementation, i.e. when implementing separate support for external network simulator.

Slave name
A unique name for the slave

The allocate keyword can be used for example in the following way:

     allocate phone MySlave


Next: , Previous: allocate keyword, Up: Remote test case control

5.9.2 free keyword

Every allocated slave must be freed with free when it becomes unused.

The free keyword has one mandatory argument, described below.

Argument
slave name
The slave name, the same that was given for allocate.

free can be used for example in the following way:

     free MySlave


Next: , Previous: free keyword, Up: Remote test case control

5.9.3 sendreceive keyword

The sendreceive keyword is used in slave script to send a variable value from slave to master. Sending a variable value from master to slave is described in Section remote keyword.

The sendreceive keyword has two mandatory arguments, described below.

Argument
variable name
The variable name.
variable value
The variable value.

The sendreceive keyword can be used for example in the following way:

     sendreceive variable1=/tmp/file.txt


Next: , Previous: sendreceive keyword, Up: Remote test case control

5.9.4 expect keyword

The expect keyword is used in slave script to expect a variable value from master. Variable must be declared by using var keyword. Expecting a variable value from slave to master is described in Section remote keyword.

The expect keyword has one mandatory argument, described below.

Argument
variable name
The name of the variable.

The expect keyword can be used for example in the following way:

     var variable1
     expect variable1


Next: , Previous: expect keyword, Up: Remote test case control

5.9.5 remote keyword

The remote keyword is used to start the execution of a test case in a slave, to request and release events from the slave and sending a variable value to a slave or expecting a variable value from a slave. Other test case controlling for remote test cases is done with the same keywords as for the local test cases.

The remote keyword has two mandatory arguments, described below.

Argument
Slave name
The slave name, the same that was given for allocate.
Command name
The remote command name (supported: run, request, wait, set, unset, release, expect, sendreceive).

The remote keyword can be used for example in the following ways:

     remote MySlave run netmodule net.cfg 5
     remote MySlave request Event1
     remote MySlave wait Event1
     remote MySlave set Event1
     remote MySlave unset Event1
     remote MySlave release Event1
     remote MySlave expect variable1
     remote MySlave sendreceive variable1=/tmp/file.txt

The remote keyword with sendreceive command is used in the master script for sending a variable value to one of the slaves identified by slave name. This remote command supports the same parameters as sendreceive keyword. See sendreceive keyword .

The remote keyword with expect command is used in master script for expecting a variable value from one of the slaves identified by slave name. This remote command supports the same parameters as the expect keyword. See expect keyword .

The other supported remote commands are run, request, release, set, unset and wait. They support the same parameters as the same keywords described in run keyword, request keyword and release keyword.


Next: , Previous: remote keyword, Up: Top

6 Using LuaScripter for creating scripted test cases

This chapter describes Lua Test Scripter feature of MIN. Lua Test Scripter feature is used for running scripted test cases where the script itself is written in Lua scripting language (www.lua.org).


Next: , Previous: Using LuaScripter for creating scripted test cases, Up: Using LuaScripter for creating scripted test cases

6.1 Overview of Lua scripting language

Lua is a modern and flexible scripting language designed to be embedded in C or C++. It gives out of the box support for arrays, variables, control structures (if/else, while, for, repeat). It has functions and even threads.

For further details, please visit www.lua.org.


Next: , Previous: Overview of Lua scripting language, Up: Using LuaScripter for creating scripted test cases

6.2 Lua Scripter test case file

The Lua Scripter uses scripts written in Lua as the test case file. Each test must be defined as a separate function which does not take any parameters and which is prefixed with "case_" statement. Test case file may contain several test functions, and some defined global variables as well. User can define its own functions inside of a test case file - every function not prefixed with "case_" will not be treated as test case.

The test case result is returned from test case function to the MIN by using return keyword.

Interaction with MIN is achieved by using MIN2Lua API which is covered in this chapter.

An example of a test case file is described below:

     function case_foo() -- Test case title
     	min.print("Hello World");
     	return TP_PASSED;
     end

Test case file may contain definitions. The definitions are global variables and can be defined as follows:

     -- Begin of define section
     MODULE = TestCaseModuleThatCanBeUsedWithLua
     -- End of define section
     
     function case_foo() -- Test case title
     	min.print(string.format("Using: %s test module",MODULE));
     end


Next: , Previous: Lua Scripter test case file, Up: Using LuaScripter for creating scripted test cases

6.3 Setting up the Lua Scripter

Lua Scripter is configured for use by adding Lua Scripter as a test module to MIN. The test case file is added as a test case file for Lua Scripter. An example:

     [New_Module]
     ModuleName=luascripter
     TestCaseFile=script.lua
     [End_Module]

Example above defines a new module for MIN (should be put in min.conf file) that uses Lua Scripter module with script.lua test case file.


Next: , Previous: Setting up the Lua Scripter, Up: Using LuaScripter for creating scripted test cases

6.4 Lua test class

In order to use user created test code with Lua Scripter it is necessary to use MIN test module which is compliant with Lua: the Lua test class module.

A new Lua test class can be easily created with MIN Test Module Template Wizard that comes with the MIN release

     $createtestmodule

A new Lua test class is now created with the given name to the given path. The next step is to create the building block methods to the test class.

To create the building block methods to the Lua test class:

  1. Implement the building blocks to the /<testclassname>/src/<testclassname>Cases.c file (there is one example method, that can be copy-pasted).
  2. Add entry lines for every method to function ts_get_test_cases (<testclassname>Cases.c):
              ENTRY(*list,"Example",ExampleTest);
    
  3. Add entry lines for every method to FORWARD DECLARATIONS:
              LOCAL int ExampleTest( lua_State *l );
    
  4. Build the test class from the /<testclassname> directory by using build.sh script. It will automatically copy test class library to /home/<user name>/.min.

Now the Lua test class is created. The next step is to implement test cases to test the test case file used by Lua Scripter. An example test case file can be found in /<testclassname>/Example.lua. The test case file is constructed using the script language defined in this chapter.

Copy the test case file to /home/<user name>/.min/

Now you should be able to execute your test class module by using console UI or EXT INTERFACE.


Next: , Previous: Lua test class, Up: Using LuaScripter for creating scripted test cases

6.5 General

This chapter describes the MIN2Lua API as well as it gives a general look on the Lua syntax.


Next: , Previous: General, Up: General

6.5.1 Test case result

Test cases defined in Lua scripting language return their results by value (as they are functions). Two macros are provided: TP_PASSED and TP_FAILED.

Example:

     function case_function() -- This is a title
     	Return TP_PASSED;
     end
     
     function case_function() -- This is a title
     	Return TP_FAILED;
     end


Next: , Previous: Test case result, Up: General

6.5.2 Test case result description

Test case result description is returned as a second value from function. It is recommended but not needed to have proper test case.

Example:

     function case_function() -- This is a title
     	Return TP_FAILED,"Test Case result description";
     end


Next: , Previous: Test case result description, Up: General

6.5.3 Test case title

The title is used to give verbal id to the test case. If test case title is defined it will be seen on the Console UI, if not then function name will be seen instead. It is recommended to add title to each test case.

Test case title is defined in the same line on which function name is written, after "--"-marks. Please note that this -- is a comment in Lua.

     function case_function() -- This is a title
     
     end

The example above shows a test case with title defined, where following example shows test case without title:

     function case_function()
     
     end

Both of them will be shown on the Console UI, which differs from standard MIN Scripter (In standard MIN Scripter test case title is mandatory).


Next: , Previous: Test case title, Up: General

6.5.4 Calling test functions in test cases

Each test case is a method exported from Test Module. First of all it is a must to load Lua Test Class as a Test Module, then you can call each test function as follows:

     function case_function() -- load test
     	foo = min.load("Bar");
     	foo.Example();
     	min.unload(foo);
     	return TP_PASSED;
     end

Note that the following call:

     foo.Example();

is referring to the test function name given in ENTRY macro. It is not the real test function name.


Next: , Previous: Calling test functions in test cases, Up: Using LuaScripter for creating scripted test cases

6.6 MIN2Lua API

Cooperation between MIN and script written in Lua is done by API defined in MIN and exported to the script. All functions are placed in min namespace.


Next: , Previous: MIN2Lua API, Up: MIN2Lua API

6.6.1 print method

The print functionality can be used to print messages on the Console UI.

     function case_function() -- print test
     	min.print("Hello World");
     	return TP_PASSED;
     end

It is also possible to use message formatting, to achieve this one must use built-in Lua string functionality called format

     function case_function() -- print test with formatting
     	min.print(string.format("Message: %s, id %d",Hello,112));
     	return TP_PASSED;
     end


Next: , Previous: print method, Up: MIN2Lua API

6.6.2 load method

The load functionality is used to load Lua Test Class provided by the end user. As a parameter it takes module name. As a result it returns a handle to the loaded Lua Test Class that can be used to call user defined test cases from the loaded Test Module.

If loading fails then returned value is nil

     function case_function() -- load test
     	foo = min.load("Bar");
     	if foo == nil then
     		return TP_FAILED;
     	end
     	foo.Example();
     	min.unload(foo);
     	return TP_PASSED;
     end

Example above will load module Bar.so (extension is added automatically) from paths specified in min.conf file. Module handler is checked then if loading has been correct.


Next: , Previous: load method, Up: MIN2Lua API

6.6.3 unload method

The unload functionality is used to unload loaded Lua Test Class. As a parameter it takes the handle to the loaded Test Module. See load method.


Next: , Previous: unload method, Up: MIN2Lua API

6.6.4 sleep method

The sleep functionality is used to pause test case execution for a specified amount of time. As a parameter it takes the time in milliseconds. Example shows 1 second sleep:

     function case_function() -- sleep example
     	min.sleep(1000);
     end


Next: , Previous: sleep method, Up: MIN2Lua API

6.6.5 request method

The request functionality is used to request an event. As a parameter it takes the name of the event to be requested and as an optional second parameter the event type which can be StateEvent or IndicationEvent. By default it is StateEvent.

Examples:

     function case_function() -- request example state event
     	min.request("Event1");
     end
     
     function case_function() -- request example state event 2
     	min.request("Event1",StateEvent);
     end
     
     function case_function() -- request example indication event
     	min.request("Event1",IndicationEvent);
     end

Note that it is needed to release event after it has been requested.

Method request may be also used to request an event from slave. See Remote test case execution.

     function case_function() -- remote example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     	slavehnd:request( "Event1");
     	min.slave_free(slavehnd);
     end


Next: , Previous: request method, Up: MIN2Lua API

6.6.6 release method

The release functionality is used to release requested event. As a parameter it takes the name of the already requested event.

     function case_function() -- release example
     	min.request("Event1");
     	min.release("Event1");
     end

Method release may be also used to release an event using slave handler.

     function case_function() -- remote example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     	slavehnd:release( "Event1");
     	min.slave_free(slavehnd);
     end


Next: , Previous: release method, Up: MIN2Lua API

6.6.7 set method

The set functionality is used to set an event. As a parameter it takes the name of the event to be set and as an optional second parameter the event type which can be StateEvent or IndicationEvent. By default the type is IndicationEvent.

Examples:

     function case_function() -- set example indication event
     	min.set("Event1");
     end
     
     function case_function() -- set example state event 2
     	min.set("Event1",StateEvent);
     end
     
     function case_function() -- set example indication event
     	min.set("Event1",IndicationEvent);
     end


Next: , Previous: set method, Up: MIN2Lua API

6.6.8 unset method

The unset functionality is used to unset a state event that has been set before. As a parameter it takes the event name. Example:

     function case_function() -- unset example
     	min.set("Event1",StateEvent);
     	min.unset("Event1");
     end


Next: , Previous: unset method, Up: MIN2Lua API

6.6.9 wait method

The wait functionality is used for waiting for requested event. Event might be requested before wait is used, but this is not a must. If event has not been requested it will be requested and released in wait function. As a parameters wait takes event name and optional event type which can be StateEvent or IndicationEvent. By default it is IndicationEvent. Example:

     function case_function() -- wait example state event
     	min.wait("Event1");
     end
     
     function case_function() -- wait example 2 state event
     	min.request("Event1");
     	min.wait("Event1");
     	min.release("Event1");
     end
     
     function case_function() -- wait example state event
     	min.wait("Event1",IndicationEvent);
     end
     
     function case_function() -- wait example 2 state event
     	min.request("Event1",IndicationEvent);
     	min.wait("Event1",IndicationEvent);
     	min.release("Event1",IndicationEvent);
     end

Note that it is a must to wait for an event of the type the event has been requested.


Next: , Previous: wait method, Up: MIN2Lua API

6.6.10 run method

The slave_allocate functionality allocates slave device which is needed for remote test case execution. As parameters it takes slave type and slave name. It returns a handle to the slave which is then used for calling methods on slave.

Available slave types are: SlaveTypePhone and SlaveTypeTablet

Example:

     function case_function() - slave_allocate example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     end

Note that the allocated slave must be freed.


Next: , Previous: run method, Up: MIN2Lua API

6.6.11 slave_allocate method

The slave_allocate functionality allocates slave device which is needed for remote test case execution. As parameters it takes slave type and slave name. It returns a handle to the slave which is then used for calling methods on slave.

Available slave types are: SlaveTypePhone and SlaveTypeTablet

Example:

     function case_function() - slave_allocate example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     end

Note that the allocated slave must be freed.


Next: , Previous: slave_allocate method, Up: MIN2Lua API

6.6.12 slave_free method

The slave_free functionality is used to free allocated slave device. As a parameter it takes handler to the slave.

Example:

     function case_function() -- run example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     	min.slave_free(slavehnd);
     end


Next: , Previous: slave_free method, Up: MIN2Lua API

6.6.13 expect method

Method expect is used to wait for variable that will be passed from slave. As a parameter it takes name of the variable under which it has been send.

     function case_function() - remote expect example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     	a = slavehnd:expect("foo");
     	min.slave_free(slavehnd);
     end


Next: , Previous: expect method, Up: MIN2Lua API

6.6.14 send method

Method send is used to send variable through external interface. As a parameter it takes the name under which it will be sent and the variable (number or string).

     function case_function() - remote expect example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     	a = 5;
     	slavehnd:send("foo",a);
     	min.slave_free(slavehnd);
     end


Next: , Previous: send method, Up: MIN2Lua API

6.6.15 Remote test case execution

It is possible to execute functionalities on the slave device with following methods:

In order to do this one must use slave handler:

     function case_function() -- remote example
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     	slavehnd:request("Event1");
     	min.slave_free(slavehnd);
     end
     
     function case_function() -- remote example 2
     	slavehnd = min.slave_allocate(SlaveTypePhone,"Slave1");
     	slavehnd.request(slavehnd,"Event1");
     	min.slave_free(slavehnd);
     end

Note that the first parameter is always slave handler. You must specify it when using '.' Or use ':' because then it is added automatically.


Next: , Previous: Remote test case execution, Up: Top

7 Python interpreter module

When using MIN, it is also possible to use python scripting language to create test case logic. MIN can treat specific Python functions as test cases, python extension module is provided that makes it possible to use MIN-specific features (like events or ability to combine test cases from other test modules).


Next: , Previous: Python interpreter module, Up: Python interpreter module

7.1 Introduction

The script language provided by "scripter" test module has several limitations. If it is needed to implement more sophisticated logic, one can use functions written in python as test cases. In that case, architecture of system is as presented on Figure below.

Min Python Scripter

"Python Interpreter" test module and "MIN" Python extension are provided with MIN release. Python Interpreter test module is seen by system like any other test module. MIN Python extension is extension module that is imported by python script that serves as test case file (this will be explained in more detail later). SUT_EXTENSION is another extension module that python script needs to import. This one, however, is implemented by tester (based on template, also provided with MIN release). This extension serves as an interface to actual system under test.


Next: , Previous: Introduction, Up: Python interpreter module

7.2 Python test module usage


Next: , Previous: Python test module usage, Up: Python test module usage

7.2.1 Configuration

To use python scripted test cases, user needs to configure python interpreter module like any other module, by appropriate entries in MIN configuration files, like in the following example (name of test case file is an example of course):

     [New_Module]
     ModuleName = pythonscripter
     TestCaseFile = pythonscript.py
     [End_Module]

Python scripter module reads script given as test case file, and uses functions with names starting with "case_" as test cases. More information on syntax of test case file will be given later. Then, python module is used as any other test module of MIN.

It should be noted, that during the execution, min modifies PYTHONPATH by appending definition of directories used to store files necessary for min python module. Appended directories are defined in min configuration file, in "ModSearchPath" entries. Variable is restored to original value after closing MIN.


Next: , Previous: Configuration, Up: Python interpreter module

7.3 Python test case definition


Next: , Previous: Python test case definition, Up: Python test case definition

7.3.1 Test case file details

Generally, just the Python script might be not enough to conduct testing. The simplest way to access the tested functionality might be from the C code, not Python code. One way to facilitate that is to use Python extension written in C. You are provided with template for that extension. This template contains a skeleton of all the functions that "Python extension" library has to contain, and stubs for example test functions. Then you can import a compiled library to you Python script, in which you can implement the logic of the test.

Apart from the simplest functionality - to load and execute a test case, MIN provides some additional features in the "test module API". Equivalent of this "API" for Python test cases is "MIN Python extension library". When this library is imported to a Python script, it gives you access to MIN functionalities such as printing to the MIN console UI, executing test cases from other modules and synchronizing test execution by events. Detailed reference of those functions will be provided later.

As was mentioned before, "Python scripter" module will read the specified Python script ("*.py"), and consider each function with name starting with "case_". If function has "docstring", contents of the docstring will be used as a title of test case by MIN, otherwise the function name will be used. If test case function returns "0", test case will be considered as passed by MIN any other value will be considered "failure" (if function returns "NULL", it is considered "crashed"). If you do not define return value for a test case function, the result will be undefined (most likely - failed).

Example below shows sample python scripter test case definition:

     import min_ext
     import sut_module1
     
     def case_ms1():
             """ping"""
             min_ext.Allocate_slave("phone_b")
             min_ext.Request_remote_event("phone_b","ping",)
             min_ext.Run_remote_case("phone_b","scripter","slave.scr",1)
             retval = min_ext.Wait_event("ping")
             if (retval == 0):
                      retval = sut_module1.Do_stuff()
             min_ext.Release_remote_event("phone_b","ping")
             min_ext.Free_slave("phone_b")
             return retval


Next: , Previous: Test case file details, Up: Python test case definition

7.3.2 MIN python extension library reference

MIN python extension library provides users with set of functions that enable them to use the same features as in other types of modules. Functions are described below (note that arguments are specified in order in which they should appear in function calls):

Print_to_cui
Prints specified message to MIN console UI
(mandatory) String
Contains message to be printed
Return value
Integer, always 0

Example:

     min_ext.Print_to_cui("Printout text")
Set_indication_event
Sets MIN event of type "indication" and specified name
(mandatory) String
Name of event to set
Return value
Integer, always 0

Example:

     min_ext.Set_indication_event("MyEventInd")
Set_state_event
Sets MIN event of type "state" and specified name
(mandatory) String
Name of event to set
Return value
Integer, always 0

Example:

     min_ext.Set_state_event("MyEventState")
Unset_event
Unsets MIN event of type "state" and specified name. Note, that only events of type "state" can be unset.
(mandatory) String
Name of event to unset
Return value
Integer, always 0

Example:

     min_ext.Unset_event("MyStateEvent")
Request_event
Requests event. If test case will be waiting for some event, it first needs to request.
(mandatory) String
Name of requested event
(optional) "state"
Keyword that should be specified if event is of type "state". If it is omitted system will assume that requested event is of type "indication"
Return value
Integer, always 0

Example:

     min_ext.Request_event("MyEventInd")
     
     min_ext.Request_event("MyEventState","state")
Release_event
Releases the previously requested event when it is not needed anymore.
(mandatory) String
Name of event to request
Return value
Integer, always 0

Example:

     min_ext.Release_event("MyEvent")
Wait_event
Waits on previously requested event
(mandatory) String
Name of event
Return value
Integer, 0 if event was properly received, other value in case of error

Example:

     min_ext.Wait_event("MyEvent")
Complete_case
Executes test case from other MIN test module. Function doesn't return until started test case finishes execution.
(mandatory) String
Name of test module
(optional)String
Name of test case file
(mandatory) String
Title of test case
Return value
Integer, result of test case (See Test Module API.)

Example:

     min_ext.Complete_case("min_hardcoded_module","testcase_title")
     
     min_ext.Complete_case("min_other_module","testcase_file","testcase_title")
Start_case
Starts asynchronous execution of test case from another module. Note that Python test case won't end until this test case finishes, but result of test case is not provided. It is possible to synchronize with this test case via events.
(mandatory) String
Name of test module
(optional)String
Name of test case file
(mandatory) String
Title of test case
Return value
Integer, always 0

Example:

     min_ext.Start_case("min_hardcoded_module","testcase_title")
     
     min_ext.Start_case("min_other_module","testcase_file","testcase_title")
Create_logger
Creates MIN logger structure (Keep in mind, that the logger created in test case has to be destroyed in the same case, otherwise there will be resource leak)
(mandatory) String
Path to log directory
(mandatory) String
Log filename
(mandatory) String
Log format (can be "html" or "txt")
Return value
Handle to MIN logger structure (used to log and destroy logger)

Example:

     My_logger = min_ext.Create_logger("/tmp","logfile.log","txt")
Log
Writes specified string to log
(mandatory) int
Handle to logger (returned by Create_log)
(optional) char
Style (can be "b" or "B" for bold, "u" or "U" for underline and "i" or "I" for italic - other values are ignored.). Styles work of course only in case of html logger.
(mandatory) String
Log message to write
Return value
Integer, always 0

Example:

     min_ext.Log(My_logger,"b","log this text")
Destroy_logger
Destroys MIN logger structures, required to free system resources allocated by Create_logger.
(mandatory) int
Handle to logger returned by Create_logger
Return value
Integer, always 0

Example:

     min_ext.Destroy_logger(My_logger)
Allocate_slave
Allocates slave device, in external controlled master/slave scenarios
(mandatory) String
Name of slave device
Return value
Integer, 0 if operation was successful, error value otherwise

Example:

     min_ext.Allocate_slave("other_device")
Free_slave
Releases slave device in external controlled master/slave scenarios
(mandatory) String
Name of slave device
Return value
Integer, 0 if operation was successful, error value otherwise

Example:

     min_ext.Free_slave("the_other_device")
Request_remote_event
Requests event from slave device in externally controlled master/slave scenarios
(mandatory) String
Name of slave device
(mandatory) String
Name of the event
(optional) "State"
Indicates if the requested event is of type state. If it is specified as a string different than "State" (case insensitive), or not specified at all, event will be considered indication event.
Return value
Integer, 0 if operation was successful, error value otherwise

Comment: After the event is requested from remote device, master test case can wait on it in the same way it would wait on local event.

Example:

     min_ext.Request_remote_event("other_device","some_indication_event")
     
     min_ext.Request_remote_event("the_other_device","some_state_event","state")
Release_remote_event
Releases previously requested remote event
(mandatory) String
Name of slave device
(mandatory) String
Name of event
Return value
Integer, 0 if operation was successful, error value otherwise

Comment: Function fails in case of problems in master/slave communication or faulty argument specification

Example:

     min_ext.Release_remote_event("other_device","event")
Run_remote_case
Executes Test case in previously allocated slave device
(mandatory) String
Name of slave device
(mandatory) String
Name of module
(optional) String
Test case filename
(mandatory) int
Number of test case
Return value
Integer, 0 if operation was successful, error value otherwise

Comment: Function is considered successful if remote test case was started. After that, only available method of communication with slave test case is by events. Result of remote test case will not be provided. However, python test case will not finish, until slave test case finishes (or external controller timeout expires).

Example:

     min_ext.Run_remote_case("other_device","hardcoded_min_module",1)
     
     min_ext.Run_remote_case("another_device","other_min_module","testcase_file",3)


Next: , Previous: MIN python extension library reference, Up: Python interpreter module

7.4 PyUnit cases wrapper

MIN release package provides also Python template/wrapper for PyUnit tests. If you have already developed tests following the PyUnit format, you can also execute those under control of MIN. To do this:


Next: , Previous: PyUnit cases wrapper, Up: Top

8 Using MIN Logger for logging purposes

This chapter contains the MIN Logger API description for guidance on how to use MIN Logger for logging purposes.

The purpose of MIN Logger is to get information from the modules in order to write different log files or to send information via Linux Syslog system to standard log output file. Logging to Null Output is also available from MIN Logger.

Figure below shows the basic architecture of MIN Logger and how it is involved in MIN. MIN Engine uses MIN Logger for Test Module Controller and Test Module logs. MIN Logger can be used when logging from test modules.

MIN Logger


Next: , Previous: Using MIN Logger for logging purposes, Up: Using MIN Logger for logging purposes

8.1 MIN Logger API

MIN Logger is divided into the following logger structures:

MinLogger
The purpose of MinLogger is to get log or data information and send that forward generating the required form.
MinTxtLogger, MinHtmlLogger, and MinDataLogger
The log or data information may be generated to different forms. The common way is to log information to a basic text file. There is also a possibility to generate a log file in HTML format that is in some cases more readable.
MinLoggerFileOutput, MinLoggerNullOutput and MinLoggerSyslogOutput
The purpose of the output methods is to write log or data information to a file or Linux Syslog output. Here is also output method for null output.


Next: , Previous: MIN Logger API, Up: MIN Logger API

8.1.1 MinLogger API

he methods of MIN Logger are listed and explained below: The main methods of MinLogger are:

MinLogger *mnl_create (const TSChar * path, const TSChar * file, unsigned int loggertype, unsigned int output, TSBool overwrite, TSBool withtimestamp, TSBool withlinebreak, TSBool witheventranking, TSBool pididtologfile, TSBool createlogdir, unsigned int staticbuffersize, TSBool unicode)
Creates MIN Logger "object".
const TSChar* path
Output directory
const TSChar* file
Output filename
unsigned int loggertype
Type of the logger that is in use
unsigned int output
Output plugin type number
TSBool overwrite
Overwrite file if exists flag
TSBool withtimestamp
Add timestamp flag
TSBool withlinebreak
Add line break flag
TSBool witheventranking
Do event ranking flag
TSBool pididtologfile
Process ID to log file flag
TSBool createlogdir
Create output directory if not exists flag
unsigned int staticbuffersize
Size of static buffer
TSBool unicode
Unicode flag
Return value
Pointer to created MIN Logger data structure
void mnl_destroy (MinLogger** mnl)
Destroys MIN Logger instance
MinLogger** mnl
The pointer reference to MinLogger data structure
Return value
none
int mnl_log (MinLogger * mnl, TSStyle style, const TSChar * format, ...);
Writes information to log
MinLogger * mnl
Pointer to the MinLogger instance to be used
TSStyle style
The style to be used
const TSChar * format
Format of the message to be logged
...
Extra parameters, according to the message format
Return value
Return error code 0 if logging operation completed successfully, else error code -1 if operation failed
mnl_write_delimiter (MinLogger * mnl)
Writes delimiter to log
MinLogger * mnl
Pointer to MIN Logger instance
Return value
none
void mnl_write_own_delimiter (MinLogger * mnl, const TSChar c, unsigned int t);
Writes user defined delimiter to log
MinLogger * mnl
Pointer to MIN Logger instance
const TSChar c
Character used as a delimiter
unsigned int t
Number of character in the delimiter string
Return value
none
unsigned int mnl_output_type (MinLogger * mnl)
Returns the information which output plug-in is used with logger
MinLogger * mnl
Pointer to MIN Logger instance
Return value
"OR" modified mask of output plug-in types that were created for this logger
unsigned int mnl_logger_type (MinLogger * mnl)
Returns the information which logs are created
MinLogger * mnl
Pointer to MIN Logger instance
Return value
"OR" modified mask of log typed plug-in types that were created


Next: , Previous: MinLogger API, Up: MIN Logger API

8.1.2 Use of MIN Logger

There are five logging output variations: file output, null output, Syslog output, stdout output and stderr output. There are also three logging format types: normal text, html and data formats. When logging system is taken into use logger output and type are passed to mnl_create() method. Other parameters consists of target logging directory, filename, additional information options and used buffer size definitions. If logger creation is completed successfully then method returns pointer to created logger data structure. If creation failed then returned pointer is INITPTR value.

     MinLogger* min_logger = mnl_create( "/temp/logs/"
                                         , "min_testing.log"
                           	             , ESHtml
                                         , ESFile
                                         , ESTrue
                                         , ESTrue
                                         , ESTrue
                                         , ESFalse
                                         , ESFalse
                           		    , ESFalse
                           		    , 1000
                           		    , ESFalse );

Writing to log output is executed by mnl_log() method and it is possible to use text styles (e.g. bold, underline or "remark" additions) and "sprintf" style string formatting with mnl_log() method. This method returns error code if log writing failed by some reason.

     int retval = mnl_log( min_logger
      	             , ESBold
                          , "Process ID = %s. Current number = %d"
                          , pid, data );

It is also possible to add pre-defined or own specific delimiter character into logging file or output.

     mnl_write_delimiter( min_logger );
     
     mnl_write_own_delimiter( min_logger, ':', 1 );

MIN Logger API includes also getting methods to check used logger output plug-in and types.

     unsigned int output_types = mnl_output_type( min_logger );
     
     unsigned int logger_types = mnl_logger_type( min_logger );

Created logger data structure will be deleted by mnl_destroy() method after logging output not needed any more. If deletion is completed successfully then the used logger pointer is set to INITPTR value.

     mnl_destroy( &min_logger );

For convenience MIN provides several macros that can be used for logging purposes. Those macros are MIN_XXX(char *format, ... ) where XXX is one of: TRACE, DEBUG, NOTICE, INFO, WARN, ERROR and FATAL. Those names indicates importance level for logged message (FATAL is the highest, TRACE is the lowest (the most verbose)).

Before one start using those macros the min_log_open(char *component, int level) function must be called. The supplied component name is then used in log messages to indicate the source of logged information, the level parameter is present only for binary compatibility and can be whatever value, usually 0.

When one is done with logger usage min_log_close() function should be called.

Typical usage looks like:

     min_log_open("Component Name",0);
     MIN_INFO("Log message number %d",1);
     MIN_DEBUG("Debug");
     min_log_close();


Next: , Previous: Use of MIN Logger, Up: Top

9 Using MIN Event System for test cases synchronization

This chapter describes the use of MIN Event System for test cases synchronization.


Next: , Previous: Using MIN Event System for test cases synchronization, Up: Using MIN Event System for test cases synchronization

9.1 Event interface for the test modules

The interface for event system is defined in file min_test_event_if.h and has three interface functions min_event_create(), min_event_destroy () and Event(). See MIN Event System usage.


Next: , Previous: Event interface for the test modules, Up: Event interface for the test modules

9.1.1 State events

The state events are used to indicate that some specific state is active or inactive. State events are cached, that is, their state is stored in Test Engine. This means that when a test case requests a state event, the state of the event is checked, and if it is active, the event is set immediately and it remains set as long as it is unset by the one who has set it. If the state is inactive, the event is set for the requesting client immediately after the event is set.

State Events

In figure above, first client 1 sets a specific state event. Then client 2 requests the event and goes waiting for it. The waiting returns immediately because the event is already set. After some processing, client 2 checks that the event is still active and after waiting returns immediately and proceeds with processing of its tasks. In the meanwhile, client 1 unsets the event, but the unset blocks because client 2 has requested the event. After client 2 releases the event, the unset returns to client 1. Client 2 starts processing again and requests the event again and goes waiting for it. Because the event is unset, the waiting blocks until client 1 sets the event and then the waiting returns to client 2. Then client 2 does its tasks and finally releases the event and client 1 unsets the event.


Next: , Previous: State events, Up: Event interface for the test modules

9.1.2 Indication events

The indication events are used to send an event that a specific occasion has happened. Indications are not cached, so in order to receive an indication, it must have been requested before the indication event is set.

Indication Events

Figure above depicts the indication event handling. Client 1 sets a specific indication event always after some specific occasion. After client 2 starts, it requests the indication event and goes waiting for it. After client 1 sets the event, the waiting returns to client 2 and it proceeds the processing. After client 2 has done its tasks, it releases the event. Then client 1 sets the event again, but because client 2 has no pending event request, it does not get the event. Next, client 2 requests the event again. Client 1 then sets the event and when client 2 goes waiting for the event, it returns immediately because the event is set. After that, client 2 goes waiting for the event again and the waiting returns to client 2 when client 1 sets the event again. Finally, client 2 releases the event.


Next: , Previous: Indication events, Up: Using MIN Event System for test cases synchronization

9.2 MIN Event System usage

MIN Event System can be used for various purposes and in different ways. As an example, a state event can be used to indicate when a phone call is active: a state event is set right after the call is connected and unset just before the call is deactivated. Some other test case may request the state event and wait until it is set, then send an SMS and release the state event after that. It is guaranteed that the state remains until the requester releases the event, which means that the called unset blocks until the release is called. An indication event can be used for example to indicate that an HTTP packet is received: An indication event is set every time when an HTTP packet has been received. Some other test case may then e.g. wait for the indication event and then start heavy loading of the system to interfere with the Web page receiving. The following is a sample code for setting a state event:

     minEventIf *s_event = min_event_create ("TestModuleState1", EState);
     event->SetType (s_event, ESetEvent);
     Event (s_event);

The following is a sample code for unsetting a state event:

     event->SetType (s_event, EUnsetEvent);
     Event (s_event);

The following is a sample code for setting an indication event:

     minEventIf *i_event = min_event_create ("TestModuleIndication1",
                                             EIndication);
     event->SetType (i_event, ESetEvent);
     Event (i_event);

The following is a sample code for requesting, waiting and releasing a state event:

     minEventIf *s_event = min_event_create ("TestModuleState1",
                                             EState);
     s_event->SetType (s_event, EReqEvent);
     Event (s_event);
     s_event->SetType (s_event, EWaitEvent);
     Event (s_event);
     /* Do something */
     s_event->SetType(s_event, ERelEvent);
     Event (s_event);

The following is a sample code for requesting, waiting and releasing an indication event:

     minEventIf *i_event = min_event_create ("TestModuleIndication1",
                                              EIndication);
     i_event->SetType (i_event, EReqEvent);
     Event (i_event);
     i_event->SetType (i_event, EWaitEvent);
     Event (i_event);
     /* Do something */
     i_event->SetType (i_event, ERelEvent);
     Event (i_event);


Next: , Previous: MIN Event System usage, Up: Top

10 Running master/slave test cases over TCP/IP

This chapter describes how MIN can be used to run master/slave test cases over TCP/IP without the need for some external controller.


Next: , Previous: Running master/slave test cases over TCP/IP, Up: Running master/slave test cases over TCP/IP

10.1 MIN Daemon

As of release 2009w19 MIN is shipped with MIN daemon (mind). The process listens to pre-defined port (51551) and when someone (master), connects that port, MIN engine is launched. The engine runs only for the duration of the slave test case.


Next: , Previous: MIN Daemon, Up: Running master/slave test cases over TCP/IP

10.2 Specifying slaves

Before running the master/slave case, the slaves must be introduced to master. This can be done with command line swith --slave hostname[slave_type]. The hostname (or ip address) is mandatory, if slave type is not given, it defaults to “phone”. It is also possible to configure slaves in min.conf file, or into a file residing in /etc/min.d/ directory.

     [Slaves]
     10.10.1.2 desktop
     maemo laptop
     somehost #defaults to phone
     [End_Slaves]

Note that, if the host name given for slave does not resolve, slave is not added to the pool of slaves. The connection with the slave is formed, when the master test case tries to alloacte slave.

In the MIN script syntax the slave type is defined when allocating the slave, for example allocate desktop slave1. This would allocate first free slave of type “desktop”.


Next: , Previous: Specifying slaves, Up: Running master/slave test cases over TCP/IP

10.3 Master/slave example

This simple example runs the first case in minDemoModule in two slaves of type “desktop” and “laptop”.

In the min.conf we have specified the slaves as in previous chapter. The master script could then look as follows.

     [Test]
     title run minDemodule in two slaves
     allocate desktop slave1
     remote slave1 run minDemoModule  dummy.cfg 1
     free slave1
     allocate laptop slave2
     remote slave2 run minDemoModule  dummy.cfg 1
     free slave2
     [Endtest]


Next: , Previous: Master/slave example, Up: Top

11 MIN Text interface usage

This chapter describes the MIN Text interface.


Next: , Previous: MIN Text interface usage, Up: MIN Text interface usage

11.1 Critical information

MIN Text interface is designed to be used, to handle C strings allocated on the heap, without worrying about the amount of memory needed to be allocated. Text interface can grow or shrink automatically.

MIN Text interface is always allocated on the heap by using tx_create method. It is required by the end user to free all allocated resource by calling tx_destroy on it.


Next: , Previous: Critical information, Up: MIN Text interface usage

11.2 Usage example

     Text *string = tx_create("MIN");  // allocate Text with "MIN"
                                       // as initializer
     
     tx_c_append(" is great");         // modification of Text data
     
     tx_destroy(&string);              // deallocate Text, and buffer
                                       // used to hold string data


Next: , Previous: Usage example, Up: MIN Text interface usage

11.3 MIN Text interface API description

Text *tx_create (const char * txt)
Creates Text structure and initializes it.
const char * txt
Initial value, C-string.
Return value
Test interface initialized with *txt value
void tx_destroy (Text ** txt)
Destroys Text structure allocated with tx_create
Text ** txt
Text interface to be destroyed
Return value
none
void tx_append (Text * dest, const Text * src)
Appends one Text interface to another
Text * dest
Text interface to append to
const Text * src
Text interface to be appended to *dest
Return value
none
void tx_copy (Text * dest, const Text * src)
Copies content of one Text to another
Text * dest
Destination Text interface
const Text * src
Source Text interface
Return value
none
void tx_c_append (Text * dest, const char *src)
Appends C string to Text interface
Text * dest
Destination Text interface to append to
const char *src
C-string to be appended to *dest
Return value
none
void tx_prepend (Text * src, Text * dest)
Prepends to one Text interface another
Text * src
Text interface to be prepended to *dest
Text * dest
Text interface to prepend to
Return value
none
void tx_c_prepend (Text * src, const char * dest)
Prepends C-string to Text interface
Text * src
Text interface to prepend to
const char * dest
C-string to be prepended to *src
Return value
none
tx_c_copy (Text * dest, const char *src)
Copies content of c string to Text interface
Text * dest
Text interface to copy the string to
const char *src
C-string to be copied to *dest
Return value
none
char *tx_get_buf (Text * txt)
Getter for C string representation of data held in Text interface
Text * txt
Text interface to copy from
Return value
Copy of data held by the Text interface
char *tx_share_buf (Text * txt)
Getter for adress of data held in Text interface
Text * txt
Text interface to get pointer from
Return value
pointer to the data held by Text interface
void tx_back_trim (Text * txt, const char *chars)
Removes specified set of characters from the end of Text
Text * txt
Text interface to remove from
const char *chars
Characters to be removed
Return value
none
char tx_at (Text * txt, unsigned int index)
Gives character from the Text that is at given position
Text * txt
Text interface
unsigned int index
index of character
Return value
Character at index position

If index exceeds the length of the data NULL byte is returned

tx_int_append (Text * dest, const char *options, int src)
Appends integer to Text interface
Text * dest
Text interface to append to
const char *options
format modifiers [flags][width][.precision][length].

Modifiers are the same as in printf (for more details see man printf)

int src
Number to append to Text interface
Return value
none


Next: , Previous: MIN Text interface API description, Up: Top

12 Test interference

The following chapter describes functionality and usage of MIN's Test Interference.


Next: , Previous: Test interference, Up: Test interference

12.1 Overview

Test interference allows programmers to execute test cases in system under stress - for some components it might be useful to see, how the code behaves if the CPU is busy, when other processes are eating up memory and so on. To simulate system load, MIN uses tools contained in sp-stress package, which is a part of Maemo SDK. Tools can simulate: cpu load, memory usage and IO operations. Test interference is usable in "coded" ("hardcoded", MINUnit and so on), as well as in scripted test cases. Tools from sp-stress package are executed in process running in parallel to test case.


Next: , Previous: Overview, Up: Test interference

12.2 Prerequisites

To use test interference, it is mandatory to have sp-stress package installed. Lack of the package will make scripted cases, that use test interference, invalid. In case of "coded" test cases - user needs to check explicitly if creation of test interference succeeded.


Next: , Previous: Prerequisites, Up: Test interference

12.3 Test Interference API

MIN provides a set of C functions, that make it possible to use test interference functionality in the same way as other MIN facilities.


Next: , Previous: Test Interference API, Up: Test Interference API

12.3.1 ti_start_interference

Function that creates test interference "instance" and starts the interference process. By "instance" we understand testInterference structure. Pointer to this structure is returned by ti_start_interference function, and is used for manipulating created interference process (pausing/resuming and stopping). When function returns, test interference process is started. As argument, function takes enumerator TInterferenceType, and value of load. TinterferenceType enumerator has the following values:

     typedef enum {
             ECpuLoad,
             EMemLoad,
             EIOLoad
     } TInterferenceType;

Enumerator (along with all test interference functions) is available if file includes the header min_test_interference.h. Function has the following prototype:

     testInterference *ti_start_interference (TInterferenceType aType,
                                                    int aLoadValue
                                                   );

and should be used in following way:

     testInterference* disturbance;
     disturbance = ti_start_interference(ECpuLoad, 75);

In case of EcpuLoad, load value holds amount of CPU time that should be taken, in percent. In case of EmemLoad, aLoadValue holds amount of memory to be taken, in megabytes. In case of IOLoad (which performs disk IO operations), this value is ignored. It should be also noted, that if it is not possible to create test interference (for any reason, including missing sp-stress package), function will return NULL. More detailed problem information can then be found in syslog.


Next: , Previous: ti_start_interference, Up: Test Interference API

12.3.2 ti_start_interference_timed

If there is need to make more complicated interference scenario (for example, to mimic "normal" device usage to some extent), ti_start_interference_timed function might be used. This causes generated disturbance to start and stop in specified time intervals, until stopped permanently. Function has the following prototype:

     testInterference *ti_start_interference_timed (TInterferenceType aType,
                                                    int aIdleTime,
                                                    int aBusyTime,
                                                    int aLoadValue
                                                   );

And should be used in the following way:

     testInterference* disturbance;
     disturbance = ti_start_interference_timed(EMemLoad,10000,10000,99);

This will cause interference process to take 99 megabytes of memory for 10000 milliseconds(10 seconds), then release it for 10 seconds, and repeat cycle until interference is stopped. aIdleTime argument specifies the time during which interference process is stopped. aBusyTime holds amount of time the interference is actually causing the disturbance. Both time values are specified in milliseconds. Return value of function follows the same rules as ti_start_interference.


Next: , Previous: ti_start_interference_timed, Up: Test Interference API

12.3.3 ti_pause_interference

Function is used to pause test interference process at any moment. It has the following prototype:

     void ti_pause_interference(testInterference* aInterference);

and can be used in the following way:

     ti_pause_interference(disturbance);

aInterference argument is pointer to testInterference structure, returned by ti_start_interference or ti_start_interference_timed function.


Next: , Previous: ti_pause_interference, Up: Test Interference API

12.3.4 ti_resume_interference

Function is used to resume previously paused interference process. If the process was not paused, call is ignored.

Function has the following prototype:

     void ti_resume_interference(testInterference* aInterference);

and can be used in the following way:

     ti_pause_interference(disturbance);

aInterference argument is pointer to testInterference structure.


Next: , Previous: ti_resume_interference, Up: Test Interference API

12.3.5 ti_stop_interference

Function used to stop and destroy previously created testInterference. Function has the following prototype:

     void ti_stop_interference(testInterference* aInterference);

and can be used in the following way:

     ti_stop_interference(disturbance);

aInterference argument is a pointer to testInterference structure, and after function returns, it will be set to NULL. Interference process will be killed. Memory taken for test interference data will be freed.


Next: , Previous: ti_stop_interference, Up: Test interference

12.4 Using test interference in scripted test cases

Test Interference can be also used in scripted test cases, by scripter commands. New keyword, testinterference is used for that. Starting interference is done in the following way:

     testinterference name command type value idle_time busy_time

testinterference - mandatory keyword

name - identifier of created testinterference

command - can have two values, "start" or "stop"

type - can have the following values: "cpuload", "memload" and "ioload". Determines type of started interference.

value - numeric parameter, for cpuload determines amount of taken CPU time in percent. For memload it holds amount of taken memory in megabytes. For ioload value is ignored.

idle_time - numeric parameter, specifies time in cycle when disturbance is stopped (in milliseconds). Giving it value 0 is equal to starting constant disturbance.

busy_time - numeric parameter, time the disturbance is active during cycle.

All numeric parameters are mandatory ( due to way parameters are handled in scripter).

Failure to call "stop" command for all "started" interferences in test case will make the case invalid.


Next: , Previous: Using test interference in scripted test cases, Up: Top

13 Compiling C++ test modules

It is possible to use C++ inside MIN test modules. Currently (since version 2009w24) a version of Test Module Template Wizard, which creates C++ enabled test module templates, is shipped with MIN. The tool is invoked with command createtestmodule++ and has exactly the same use as the traditional wizard (createtestmodule).


Next: , Previous: Compiling C++ test modules, Up: Top

14 MIN DBus interface

MIN DBus interface allows external clients to interact with MIN through DBus subsystem. All functionalities that are available in MIN are in through DBus thus one can implement a fully functional MIN client interface in one of the programming or scripting language which has DBus bindings, for example: Python. MIN exposes methods that can be called by external clients as well as it uses signals to communicate back with the external client. Exposed methods:

min_add_test_module (const char *path)
Adds module to the MIN on the runtime. Added module is specified by a path. As a result new_module or no module signal is emitted.
const char *path
Full path to the module that is going to be added.
min_add_test_case_file (unsigned int moduleid, const char *testcasefile)
Loads test case file for the specified test module.
unsigned int moduleid.
Id of the module to which test case file will be added.
const char *testcasefile
Name of the test case file to be loaded.
min_start_case (unsigned int moduleid, unsigned int caseid, unsigned int groupid)
Starts test case indicated by caseid, from test module specified by modulename. Last parameter is used is sequential case execution, and indicates the group case belongs to. It is up to external client to use this value but it is not required, it is safe to put 0 here. As a result case_started signal is emitted.
unsigned int moduleid
Indicates the test module
unsigned int caseidid
Specifies the test case in the module
unsigned int groupid
Indicates the group the test case belongs to.
min_pause_case (long testrunid)
Pauses already running case. As a result case_paused signal is emitted.
long testrunid
Indicates the ongoing case to be paused.
min_resume_case (long testrunid)
Resumes already paused case. As a result case_resumed signal is emitted.
long testrunid
Indicates the paused case to be resumed.
min_abort_case (long testrunid)
Aborts ongoing or paused case. As a result case_result signal is emitted.
long testrunid
Indicates test case to be aborted.
min_query_test_modules
Orders MIN to provide list of available test modules that can be added. As a result min_test_modules signal is emitted
min_query_test_files
Orders MIN to provide list of available test case files that can be loaded. As a result min_test_files signal is emitted

Exposed signals:

min_test_modules (const char *modules)
Emited when client uses min_query_test_modules functionality. Carries list of modules which are available for loading.
const char *modules
String which contains paths to modules. Each entry is delimited by NULL-Byte, end of string contains double null byte: entry\0entry\0entry\0\0
min_test_files (const char *files)
Emited when client uses min_query_test_files functionality. Carries list of files which are available for loading.
const char *files
String which contains paths to files. Each entry is delimited by NULL-Byte, end of string contains double null byte: entry\0entry\0entry\0\0
min_new_module (const char *modulename, unsigned int moduleid)
Emitted when min_add_test_module has finished with success.
const char *modulename
The path to the module which has been added (client passes it to min_add_test_module)
unisgned int moduleid
The id number for added module given by MIN. In all future communication with MIN this id should be used to reference this module.
min_no_module (const char *modulename)
Emitted when min_add_test_module ends with failure.
const char *modulename
The path to the module which has been added (client passes it to min_add_test_module)
min_module_ready (unsigned int moduleid)
Emitted when all test cases for the given module has been enumerated end delivered to the client (min_new_test_case signal)
unsigned int moduleid
The id of the module which is a subject of this message.
min_new_test_case (unsigned int moduleid, unsigned int caseid, const char *casetitle)
Emitted when test module has been added (min_add_test_module and min_add_test_case_file has been executed). Carries information abour single case availabie in a given module, client recieves as many of those signals as the number of test cases in the module. End of transmission is indicated by module_ready signal.
unsigned int moduleid
The id of the module to which the test case belongs to.
unsigned int caseid
The unique id of the test case within test module.
const char *casetitle
The title fo the test case.
min_case_started (unsigned int mosuleid, unsigned int caseid, long testrunid)
Emitted when test case execution has been started by call to min_start_case.
unsigned int moduleid
The id of the module to which the test case belongs to.
unsigned int caseid
The unique id of the test case which has been executed.
long testrunid
The id of the test run in which the test case has been executed.
min_case_paused (long testrunid)
Emitted as a confirmation that test case has been paused.
long testrunid
Indicates the id of a test run which has been paused.
min_case_resumed (long testrunid)
Emitted as a confirmation that test case has been resumed.
long testrunid
Indicates the id of a test run which has been resumed.
min_case_result (long testrund, int result, const char *desc, long startime, long endtime)
Enitted after the test case has been finished, or starting of test case has been unsuccessfull.
long testrunid
Indicates the test run id that has finished and transmits it's result.
int result
The test case result: - test case crashed: -2 - test case timeouted: -1 - test case passed: 0 - test case failed: 1 - test case aborted: 2
const char *desc
Test result description.
long starttime
Start time of the test case, unix timestamp.
long endtime
End time of the test case, unix timestamp.
min_case_msg (long testrunid, const char *message
Forwards user message from test process to the UI level so that it can be visible by the end user.
long testrunid
The id of the test run which prints
const char *message
Message to be printed.


Previous: MIN DBus interface, Up: Top

Appendix A GNU Free Documentation License

GNU Free Documentation License
		  Version 1.2, November 2002


 Copyright (C) 2000,2001,2002  Free Software Foundation, Inc.
     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


0. PREAMBLE

The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.

This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense.  It
complements the GNU General Public License, which is a copyleft
license designed for free software.

We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does.  But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book.  We recommend this License
principally for works whose purpose is instruction or reference.


1. APPLICABILITY AND DEFINITIONS

This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License.  Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein.  The "Document", below,
refers to any such manual or work.  Any member of the public is a
licensee, and is addressed as "you".  You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.

A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject.  (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.)  The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.

The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License.  If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant.  The Document may contain zero
Invariant Sections.  If the Document does not identify any Invariant
Sections then there are none.

The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License.  A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.

A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters.  A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text.  A copy that is not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification.  Examples of
transparent image formats include PNG, XCF and JPG.  Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.

The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page.  For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.

A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language.  (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".)  To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.

The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document.  These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.


2. VERBATIM COPYING

You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License.  You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute.  However, you may accept
compensation in exchange for copies.  If you distribute a large enough
number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and
you may publicly display copies.


3. COPYING IN QUANTITY

If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover.  Both covers must also clearly and legibly identify
you as the publisher of these copies.  The front cover must present
the full title with all words of the title equally prominent and
visible.  You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.

If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.

It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.


4. MODIFICATIONS

You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it.  In addition, you must do these things in the Modified Version:

A. Use in the Title Page (and on the covers, if any) a title distinct
   from that of the Document, and from those of previous versions
   (which should, if there were any, be listed in the History section
   of the Document).  You may use the same title as a previous version
   if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities
   responsible for authorship of the modifications in the Modified
   Version, together with at least five of the principal authors of the
   Document (all of its principal authors, if it has fewer than five),
   unless they release you from this requirement.
C. State on the Title page the name of the publisher of the
   Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
   adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license notice
   giving the public permission to use the Modified Version under the
   terms of this License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections
   and required Cover Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled "History", Preserve its Title, and add
   to it an item stating at least the title, year, new authors, and
   publisher of the Modified Version as given on the Title Page.  If
   there is no section Entitled "History" in the Document, create one
   stating the title, year, authors, and publisher of the Document as
   given on its Title Page, then add an item describing the Modified
   Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for
   public access to a Transparent copy of the Document, and likewise
   the network locations given in the Document for previous versions
   it was based on.  These may be placed in the "History" section.
   You may omit a network location for a work that was published at
   least four years before the Document itself, or if the original
   publisher of the version it refers to gives permission.
K. For any section Entitled "Acknowledgements" or "Dedications",
   Preserve the Title of the section, and preserve in the section all
   the substance and tone of each of the contributor acknowledgements
   and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document,
   unaltered in their text and in their titles.  Section numbers
   or the equivalent are not considered part of the section titles.
M. Delete any section Entitled "Endorsements".  Such a section
   may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled "Endorsements"
   or to conflict in title with any Invariant Section.
O. Preserve any Warranty Disclaimers.

If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant.  To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.

You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.

You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version.  Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity.  If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.


5. COMBINING DOCUMENTS

You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.

The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy.  If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications".  You must delete all sections
Entitled "Endorsements".


6. COLLECTIONS OF DOCUMENTS

You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.


7. AGGREGATION WITH INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.


8. TRANSLATION

Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections.  You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers.  In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.

If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.


9. TERMINATION

You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License.  Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License.  However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.


10. FUTURE REVISIONS OF THIS LICENSE

The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation License from time to time.  Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.  See
http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation.  If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.


ADDENDUM: How to use this License for your documents

To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:

    Copyright (c)  YEAR  YOUR NAME.
    Permission is granted to copy, distribute and/or modify this document
    under the terms of the GNU Free Documentation License, Version 1.2
    or any later version published by the Free Software Foundation;
    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
    Texts.
    A copy of the license is included in the section entitled "GNU
    Free Documentation License".

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the "with...Texts." line with this:

    with the Invariant Sections being LIST THEIR TITLES, with the
    Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.

If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License,
to permit their use in free software.