Commit 02b0a09b authored by Elemer Lelik's avatar Elemer Lelik
Browse files

change to asciidoc

parent 54899a87
......@@ -7,4 +7,5 @@
/TITAN_Executor_API/nbbuild/
/TITAN_Executor_API/dist/
/TITAN_Executor_API_Demo/dist/
/TITAN_Executor_API_test/build/
\ No newline at end of file
/TITAN_Executor_API_test/build/
---
Author: Arpad Lovassy
Version: 8/198 17-CRL 113 200/6, Rev. PE1
Date: 2018-06-19
---
= Titan Executor API User Guide
:author: Arpad Lovassy
:revnumber: 8/198 17-CRL 113 200/6, Rev. PE1
:revdate: 2018-06-19
:title-logo-image: images/titan_logo.png
:toc:
ifdef::env-github,backend-html5[]
image::images/titan_logo.png[alt]
endif::[]
*Abstract*
This document describes detailed information of using the TITAN Executor API.
*Copyright*
Copyright (c) 2000-2018 Ericsson Telecom AB +
All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v2.0 that accompanies this distribution and is available at +
https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html.
*Disclaimer*
The contents of this document are subject to revision without notice due to continued progress in methodology, design and manufacturing. Ericsson shall have no liability for any error or damage of any kind resulting from the use of this document.
= Overview
The Titan Executor API provides the following functionalities:
* execution control as in mctr_gui
* callback for host controller connecting events
* console log callback
It is implemented in Java using JNI calls to the C++ side, which is based on the implementation of titan_eclipse JNI executor. The Titan Executor API is independent from Eclipse.
= Titan Executor API
== Prerequisites
* TITAN installed (_libmctrjninative.so_ library file is in _TTCN3_DIR/lib_, and library path is in `LD_LIBRARY_PATH`)
* Java JRE 1.7 installed
== Install
Copy _lib/TITAN_Executor_API.jar_ to your classpath.
== Usage
The entry point of the API is the `com.ericsson.titan.executor.api.JniExecutor`, and the client must implement `com.ericsson.titan.executor.api.IJniExecutorObserver` interface for the callbacks.
For further details see the Javadoc embedded in the project.
= Titan Executor API Demo
== Install
Copy _TITAN_Executor_API_Demo.jar_ and _lib/TITAN_Executor_API.jar_ to any selected directory, so keep the directory structure, make sure, that _TITAN_Executor_API.jar_ is in _lib/_, so it means, that Titan Executor API is in the classpath, which is defined in the manifest file of _TITAN_Executor_API_Demo.jar_.
== Usage
To start the demo the following command must be used:
[source]
java -jar <install directory>/TITAN_Executor_API_Demo.jar
= Javadoc
== Install
Extract javadoc directory from the zip file
== Usage
Open _javadoc/index.html_ from a browser.
---
Author: Jenő Balaskó
Version: 109 21-CRL 113 200/6-4, Rev. A
Date: 2018-05-16
---
= Product Revision Information for TITAN
:author: Jenő Balaskó
:revnumber: 109 21-CRL 113 200/6-4, Rev. A
:revdate: 2018-05-16
:toc:
= Product Revision
== Product
[cols=",,,",options="header",]
|===
|Product number |Old Rev |New Rev |Function designation
|CRL 113 200/6 |R3B |R4A |TTCN-3 Executor
|===
This release is done to deliver updated and improved TTCN related products to all customers within and outside Ericsson.
== Subordinate product release
Legend: R = Revised, N = New, C = Cancelled, E = Equal
[cols=",,,,",options="header",]
|===
|Name |Product |Old R-State |New R-State |Status
|*Titan* |*CRL 113 200/6* |*R3B* |*R4A* |N
|Editline Library (libedit) |2/CAX 105 4373 | |R1A |E
|GNU C Library (glibc) |7/CAX 105 3195 | |R1A |E
|LibXML2 |8/CAX 105 3282 | |R1A |E
|OpenSSL |4/CAX 105 3048 | |R1A |E
|Cygwin |1/CAX 105 3757 | |R1A |E
|===
== Affected documents
Important note: *The documents are available via the hyperlinks.*
Legend: R = Revised, N = New, C = Cancelled, E = Equal
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Old Revision |New Revision |
|link:https://github.com/eclipse/titan.core/blob/master/usrguide/releasenotes.adoc[Release Notes for TITAN TTCN-3 Test Executor 109 47-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.core/blob/master/usrguide/installationguide.adoc[Installation guide for TITAN TTCN-3 Test Executor 1/1531-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.EclipsePlug-ins/blob/master/Eclipse_installationguide.adoc[Installation Guide for TITAN Designer and TITAN Executor for the Eclipse IDE 3/1531-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.core/blob/master/usrguide/userguide/README.adoc[User Guide for TITAN 1/198 17-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.core/blob/master/usrguide/referenceguide/README.adoc[Programmers Technical Reference for TITAN TTCN-3 Test Executor 2/198 17-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.EclipsePlug-ins/blob/master/Eclipse_Designer_userguide/README.doc[User Guide for the TITAN Designer for the Eclipse IDE 4/198 17-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.EclipsePlug-ins/blob/master/Eclipse_Executor_userguide/README.doc[User Guide for the TITAN Executor for the Eclipse IDE 5/198 17-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.core/blob/master/usrguide/apiguide/README.doc[API Technical Reference for TITAN TTCN-3 Test Executor 6/198 17-CRL 113 200/6] |B |Cloud stored |R
|link:https://github.com/eclipse/titan.core/blob/master/titan_executor_api/doc/Titan_Executor_API_User_Guide.doc[Titan Executor Java API user guide 8/198 17-CRL 113 200/6] |B |Cloud stored |R
|Programmers Tech. Reference Guide for Titanium |B |Cloud stored |R
|Titanium Description |B |Cloud stored |R
|Statement of Compliance for Eclipse Titan |B |Cloud stored |R
|Statement of Compliance for use of XML schema in Eclipse Titan |B |Cloud stored |R
|===
= Reason for revision
== Implementations Proposals
See embedded document for details.
== Change Requests
See embedded document for details.
== Exemption Requests
== Trouble Reports
=== Implemented Trouble Reports
See embedded document for details.
=== Not Implemented Trouble Reports
=== Embedded slide with details
This diff is collapsed.
This diff is collapsed.
= Introduction
== Overview
This document describes the TITAN API on C\++ level. It is intended for users who write test port implementation, external function implementation in language C++ and want to use the available resources of TITAN.
Detailed information can be found on the following topics:
* test ports, the communication link between the TITAN Executor and System Under Test (SUT);
* built-in encoding and decoding functions;
* TTCN-3 data mapping to C++ constructs;
* troubleshooting for common TTCN-3 related issues and problems.
== Target Groups
This document is intended for advanced users of the TITAN API on C++ level.
== Typographical Conventions
This document uses the following typographical conventions:
*Bold* is used to represent graphical user interface (GUI) components such as buttons, menus, menu items, dialog box options, fields and keywords, as well as menu commands. Bold is also used with ’+’ to represent key combinations. For example, *Ctrl+Click*
The '*/*' character is used to denote a menu and sub-menu sequence. For example, *File / Open*.
`Monospaced` font is used represent system elements such as command and parameter names, program names, path names, URLs, directory names and code examples.
`*Bold monospaced*` font is used for commands that must be entered at the Command Line Interface (CLI), For example, `*ttcn3_start*`
This diff is collapsed.
= Logger Plug-ins
:toc:
== Implementing Logger Plug-ins
All logger plug-ins must implement the `ILoggerPlugin` interface class in `ILoggerPlugin.hh` in `${TTCN3_DIR}/include`. Each plug-in should provide some essential information on itself and should implement some basic functions:
The name `(name_, plugin_name())` of the plugin. To be able to reference the plugin (for example for configuration). Additional information about the plug-in `(help_, plugin_help())`.
The minimum API version number the plug-in is compatible with `(major_version_, major_version()`, `minor_version_, minor_version())`.
Each plug-in must have an initialization `(init())` and deinitialization `(fini())` routine, which are called at the begin and end of the plug-in’s lifecycle. The same functionality can be implemented in the plug-in’s constructor and destructor as well.
The plug-in could be asked, whether it’s configured or not `(is_configured())`. For example the file is already opened, the database connection is set up etc. Depending on this information event buffering can be enabled or disabled.
One plug-in should provide `log2str()` functionality. The `is_log2str_capable()` function should be overridden to return true. At the moment it’s not possible to change the default behavior and returning true will not have an effect except a warning.
The logger plug-ins receive the log events via the `log()` function. The details about event handling can be found in 3.3.
The generated, runtime specific (load-test or function-test) header file `TitanLoggerApi.hh` needs to be included by every logger plug-in depending on the runtime it is compiled for. These header files can be found in `${TTCN3_DIR}/include/{RT1/RT2}`. An example to handle these include files in a logger plug-in’s code:
[source]
----
#ifndef TITAN_RUNTIME_2
#include ``RT1/TitanLoggerApi.hh''
#else
#include ``RT2/TitanLoggerApi.hh''
#endif
----
Unfortunately, the `dlopen()` API is a C API, not a C\++ API, but each logger plug-in is a class, which needs to be instantiated. To resolve this, the logger plug-ins are always instantiated and destroyed through C factory functions. These functions are mandatory for all logger plug-ins and they must follow C-style linkage rules. Otherwise, the function names would be mangled by the C++ compiler, using its own, implementation dependent mangling mechanism, and `dlsym()` and such functions would not be able to locate the correct symbol in the SOs of the logger plug-ins. These functions look pretty simple:
[source]
----
#ifdef __cplusplus
extern "C"
{
ILoggerPlugin *create_plugin()
{ return new MyPlugin(); }
void destroy_plugin(ILoggerPlugin *plugin)
{ delete plugin; plugin = NULL; }
}
#endif
----
== Building Logger Plug-ins
The generated, runtime specific (load-test or function-test) header file `TitanLoggerApi.hh` needs to be included by every logger plug-in depending on the runtime it is compiled for. These header files can be found in `${TTCN3_DIR}/include/{RT1/RT2}` and this directory must be present (for example as part of `CPPFLAGS` in the `Makefile`) while compiling the logger plug-ins.
To make logger plug-ins dynamically loadable at runtime the logger plug-ins need to be built as shared libraries. Physically SOs `(.so)` on Unix and Linux platforms, DLLs `(.dll)` on Cygwin and Windows platforms. A HOWTO on building shared libraries can be found at http://tldp.org/HOWTO/Program-Library-HOWTO/index.html[David A. Wheeler, Program Library HOWTO]. A quick summary:
All the sources of the logger plug-ins need to be compiled with `–fPIC`, for example add `CXXFLAGS += -fPIC` into the `Makefile` or command line.
The linker should be instructed to create a shared library instead of an executable with the `–shared` flag. `–fPIC` is necessary here as well, for example add `LDFLAGS += -fPIC –shared` in the `Makefile` or command line.
Another thing to keep in mind is that logger plug-ins need to be linked with the dynamically linked TITAN runtime libraries (for example `libttcn3-dynamic.so/libttcn3-parallel-dynamic.so` or `libttcn3-rt2-dynamic.so/libttcn3-rt2-parallel-dynamic.so`) instead of the static ones (for example `libttcn3.a/libttcn3-parallel.a` or `libttcn3-rt2.a/libttcn3-rt2-parallel.a`). So, if all possible combinations need to be supported by a logger plug-in, all of the four versions need to be built, additionally there are naming rules to simplify making a distinction between them:
* Single mode, load test runtime. File name must end with ".so".
* Single mode, function test runtime. File name must end with "-rt2.so".
* Parallel mode, load test runtime. File name must end with "-parallel.so".
* Parallel mode, function test runtime. File name must end with "-parallel-rt2.so".
The runtime library linked with a logger plug-in must be selected to match the runtime linked with the test executable that loads it: if the test executable is linked to `libttcn3-dynamic.so`, then any logger plug-ins must also be linked to `libttcn3-dynamic.so` and not `libttcn3-parallel-dynamic.so` or `libttcn3-rt2-dynamic.so`. To ensure consistency, only a dynamic runtime library will load a logger plug-in (because a plug-in is always linked to a dynamic runtime library). If a non-dynamic runtime library is configured to load a logger plug-in, it will cause a runtime error.
Please note that linking a plug-in or any TTCN-3 project with the object files generated from the `TitanLoggerApi` or `TitanLoggerControl` internal modules and using the dynamic libraries of TITAN at the same time is not recommended and it can lead to various runtime errors.
== Event Handling
The log events are distributed to all active logger plug-ins via a four-parameter callback function with the following signature:
[source]
----
void log(const TitanLoggerApi::TitanLogEvent& event, bool
log_buffered, bool separate_file, bool use_emergency_mask);
----
The first parameter event is the event itself, the second parameter `log_buffered` indicates, whether the event is coming from an internal buffer or not, `separate_file` and `use_emergency_mask` are configuration options for emergency logging. The `use_emergency_mask` flag indicates that the given event is an emergency event and should be handled in a special way by the plug-ins, the `separate_file` flag indicates that all the emergency events should be handled separately (for example written into a separate file). For more details on emergency logging please check link:https://github.com/eclipse/titan.core/tree/master/usrguide/referenceguide[Programmer's Technical Reference]. In this function, the plug-in can handle the log events individually depending on the event’s type (that is, the alternative selected in the union `event.logEvent().choice()).`
`TitanLoggerApi::TitanLogEvent` is a generated type defined in TitanLoggerApi.xsd, which can be found in `${TTCN3_DIR}/include`. This file contains all the necessary type definitions a logger plug-in should be aware of. The corresponding header files generated from this XSD file can be found in `${TTCN3_DIR}/include/{RT1/RT2}`. The mapping between TTCN-3 types and C\++ types is defined in link:5-mapping_ttcn3_data_types_to_c+\+_constructs.adoc[Mapping TTCN–3 Data Types to C++ Constructs].
//The mapping between XSD and TTCN-3 types is defined in *Error! Reference source not found.*
== Execution
When a logger plug-in is compiled (the SO is ready) it should be configured in the configuration file. For details check link:https://github.com/eclipse/titan.core/tree/master/usrguide/referenceguide[Programmer's Technical Reference]. Additionally, `LD_LIBRARY_PATH` should contain the directory of the plug-in and `${TTCN3_DIR}/lib` as well. If the runtime linker (the loader) is unable to find any of the given logger plug-ins an error will be given.
This diff is collapsed.
= Tips & Troubleshooting
:table-number: 34
:toc:
Information not fitting in any of the previous chapters is given in this chapter.
[[migrating-existing-c-code-to-the-naming-rules-of-version-1-7]]
== Migrating Existing C++ Code to the Naming Rules of Version 1.7
When using the new naming rulesfootnote:[The new naming rules are used by default; the naming rules can be changed using the compiler command line switch -N.] the compiler generates a C\++ namespace for each TTCN–3 and ASN.1 module. The name of the namespace corresponds to the module. The generated C++ entities of a module are all placed in its namespace; therefore all the test port or protocol module code must use these namespaces.
Rules to follow when writing C++ code:
* When referencing an entity located in a different module its C++ name has to be prefixed with the namespace name of that module.
* A test port class must be placed into the namespace of its module.
* Encoding and decoding functions must be placed into the namespace of the TTCN–3 module in which the external function was defined.
* All C\++ entities have to be placed into namespace. An exception to this may be C++ entities used only locally; these are defined with the keyword `static`.
* For convenience the `using namespace` directive can be used in C++ source files. It is forbidden to use this directive in header files!
* C++ enum types are placed in the scope of their value class; enum types have to be prefixed by the C++ name of the value class.footnote:[The enum hack option has become obsolete with the new naming rules.]
[[using-external-c-functions-in-ttcn-3-test-suites]]
== Using External C++ Functions in TTCN–3 Test Suites
Sometimes standard library functionsfootnote:[C language functions cannot be called directly from TTCN–3; you need at least a wrapper function for them.] are called in the test suite or there is a need for efficiently implemented "bit-crunching" functions in the TTCN–3 ATS. In these cases functions to be called from the test suite can be developed in C++.
There are the standard library functions as well as other libraries in the C++ functions. The logging and error handling facilities of the run-time environment are also available as in case of Test Ports.
Since version 1.4.pl1 the semantic analyzer of the compiler checks the import statements thoroughly. Therefore one cannot use the virtual C++ modules as before: C++ functions must be defined as external functions to be accessible from TTCN–3 modules.
For example, the following definitions make two C++ functions accessible from TTCN–3 module `MyModule` and from any other module that imports `MyModule`.
[[example-ttcn-3-module-mymodule-ttcn]]
=== Example TTCN–3 Module (MyModule.ttcn)
[source]
----
module MyModule {
[...]
external function MyFunction(integer par1, in octetstring par2)
return bitstring;
external function MyAnotherFunction(inout My_Type par1,
out MyAnotherType par2);
[...]
}
----
The compiler will translate those external function definitions to C++ function prototypes in the generated header file `MyModule.hh`:
[source]
----
[...]
extern BITSTRING MyFunction(const INTEGER& par1, const OCTETSTRING& par2);
extern void MyAnotherFunction(My__Type& par1, MyAnotherType& par2);
[...]
----
Both pre-defined and user-defined TTCN–3 data types can be used as parameters and/or return types of the C\++ functions. The detailed description of the equivalent C++ classes as well as the name mapping rules are described in chapter <<4-encoding_and_decoding.adoc#xml-encoding-xer,XML Encoding (XER)>>.
Using templates as formal parameters in external functions is possible, but not recommended because the API of the classes realizing templates is not documented and subject to change without notice.
The formal parameters of external TTCN–3 functions are mapped to C++ function parameters according to the following table:
.TTCN–3 formal parameters and their C++ equivalents
[cols=",",options="header",]
|==============================================
|TTCN–3 formal parameter |Its C++ equivalent
|`[in] MyType myPar` |`const MyType& myPar`
|`out MyType myPar` |`MyType& myPar`
|`inout MyType myPar` |`MyType& myPar`
|`[in] template MyType myPar` |_Not recommended._
|==============================================
NOTE: In versions 1.6.pl3 and earlier the in keyword had an extra meaning in formal parameter lists. According to the TTCN–3 standard the parameter definitions `MyType myPar` and in `MyType myPar` are totally equivalent, but the earlier versions of the compiler distinguished them. Unless the keyword `in` was present the compiler passed the parameter by value (involving a copy constructor call) instead of using a const reference. That is why it was recommended to use an explicit in keyword in parameter lists of external functions.
Due to the strictness of the TTCN–3 semantic analyzer one cannot use C/C++ data types with external functions as formal parameters or return types, only TTCN–3 and ASN.1 data types are allowed. Similarly, one cannot use pointers as parameters or return values because they have no equivalents in TTCN–3 .
The external functions can be implemented in one or more C\++ source files. The generated header file that contains the prototypes of the external functions shall be included into each C++ source file. This file makes accessible all built-in data types, the user-defined types of the corresponding TTCN–3 module and all available services of the run-time environment (logging, error handling, etc.).
The name, return type and the parameters of the implemented C++ functions must match exactly the generated function prototypes or the compilation will fail. The generated function prototype is in the namespace of the module, therefore the implementation of the function has to be placed in that namespace, too.
[[logging-in-test-ports-or-external-functions]]
== Logging in Test Ports or External Functions
When developing Test Ports or external functions the need may arise for debug messages. Instead of using `printf` or `fprintf`, there is a simple way to put these messages into the log file of test executor. This feature can be also useful in case when an error or warning situation is encountered in the Test Port, especially when decoding an incoming message.
There is a class called `TTCN_Logger` in the Base Library, which takes care of logging. For historical reasons it has a static instance (object), which is called `TTCN_logger`. Since all member functions of `TTCN_Logger` are static, they can be and should be called without the logger object. The usage of object `TTCN_logger` should be avoided in newly written code.
The class `TTCN_Logger` provides some public member functions. Using them any kind of message can be put into the log file. There are two ways to log a single message, the unbuffered and the buffered mode.
=== Unbuffered Mode
In unbuffered mode the message will be put into log immediately as a separate line together with a time stamp. Thus, the entire message must be passed to the logger class at one function call. The log member function of the logger class should be used. Its prototype is:
[source, subs="+quotes"]
static void TTCN_Logger::log(int severity, const char *fmt, …);
The parameter severity is used for filtering the log messages. The allowed values of the parameter are listed in table "First level (coarse) log filtering" in the link:https://github.com/eclipse/titan.core/tree/master/usrguide/referenceguide[Programmer's Technical Reference]. We recommend using in Test Ports only `TTCN_WARNING`, `TTCN_ERROR` and `TTCN_DEBUG`. The parameter `fmt` is a pointer to a format string, which is interpreted as in `printf(3)`. The dots represent the optional additional parameters that are referred in format string. There is no need to put a newline character at the end of format string; otherwise the log file will contain an empty line after your entry.
Here is an example, which logs an integer value:
[source]
----
int myVar = 5;
TTCN_Logger::log(TTCN_WARNING, ``myVar = %d'', myVar);
----
Sometimes the string to be logged is static. In such cases there is no need for `printf`-style argument processing, which may introduce extra risks if the string contains the character `%`. The logger class offers a function for logging a static (or previously assembled) string:
[source, subs="+quotes"]
static void TTCN_Logger::log_str(int severity, const char *str);
The function `log_str` runs significantly faster than log because it bypasses the interpretation of the argument string.
There is another special function for unbuffered mode:
[source]
----
static void TTCN_Logger::log_va_list(int severity, const char *fmt,
va_list ap);
----
The function `log_va` list resembles to log, but it takes the additional `printf` arguments in one va_list structure; va_list is defined in the standard C header file `stdarg.h` and used in functions with variable number of arguments.
This function (and especially its buffered mode version, `log_event_va_list`) is useful if there is a need for a wrapper function with `printf`-like syntax, but the message should be passed further to `TTCN_Logger`. With these functions one can avoid the handling of temporary buffers, which could be a significant performance penalty.
=== Buffered Mode
As opposite to the unbuffered operation, in buffered mode the logger class stores the message fragments in a temporary buffer. New fragments can be added after the existing ones. When finished, the fragments can be flushed after each other to the log file as a simple message. This mode is useful when assembling the message in many functions since the buffer management of logger class is more efficient than passing the fragments as parameters between the functions.
In buffered mode, the following member functions are available.
[[begin-event]]
==== begin_event
`begin_event` creates a new empty event buffer within the logger. You have to pass the severity value, which will be valid for all fragments (the list of possible values can be found in the table "First level (coarse) log filtering" in the link:https://github.com/eclipse/titan.core/tree/master/usrguide/referenceguide[ Technical Reference]. If the logger already has an unfinished event when begin event is called the pending event will be pushed onto an internal stack of the logger. That event can be continued and completed after finishing the newly created event.
[source, subs="+quotes"]
static void TTCN_Logger::begin_event(int severity);
[[log-event]]
==== log_event
`log_event` appends a new fragment at the end of current buffer. The parameter `fmt` contains a `printf` format string like in unbuffered mode. If you try to add a fragment without initializing the buffer by calling begin event, your fragment will be discarded and a warning message will be logged.
[source, subs="+quotes"]
static void TTCN_Logger::log_event(const char *fmt, …);
[[log-char]]
==== log_char
`log_char` appends the character c at the end of current buffer. Its operation is very fast compared to `log_event`.
[source, subs="+quotes"]
static void TTCN_Logger::log_char(char c);
[[log-event-str-and-log-event-va-list]]
==== log_event_str and log_event_va_list
The functions `log_str` and `log_va_list` also have the buffered versions called `log_event_str` and `log_event_va_list`, respectively. Those interpret the parameters as described in case of unbuffered mode.
[source]
----
static void TTCN_Logger::log_event_str(const char *str);
static void TTCN_Logger::log_event_va_list(const char *fmt, va_list ap);
----
[[os-error]]
==== OS_error
The function `OS_error` appends the textual description of the error code stored in global variable `errno` at the end of current buffer. Thereafter that variable `errno` will be set to zero. The function does nothing if the value of `errno` is already zero. For further information about possible error codes and their textual descriptions please consult the manual page of `errno(3)` and `strerror(3)`.
[source, subs="+quotes"]
static void TTCN_Logger::OS_error();
==== log
The C++ classes of predefined and compound data types are equipped with a member function called `log`. This function puts the actual value of the variable at the end of current buffer. Unbound variables and fields are denoted by the symbol `<unbound>`. The contents of TTCN–3 value objects can be logged only in buffered mode.
[source, subs="+quotes"]
void <any TTCN-3 type>::log() const;
[[end-event]]
==== end_event
The function `end_event` flushes the current buffer into the log file as a simple message, then it destroys the current buffer. If the stack of pending events is not empty the topmost event is popped from the stack and becomes active. The time stamp of each log entry is generated at the end and not at the beginning. If there is no active buffer when `end_event` is called, a warning message will be logged.
[source, subs="+quotes"]
static void TTCN_Logger::end_event();
If an unbuffered message is sent to the logger while the buffer contains a pending event the unbuffered message will be printed to the log immediately and the buffer remains unchanged.
=== Logging Format of TTCN-3 Values and Templates
TTCN-3 values and templates can be logged in the following formats:
TITAN legacy logger format: this is the default format which has always been used in TITAN
TTCN-3 format: this format has ttcn-3 syntax, thus it can be copied into TTCN-3 source files.
Differences between the formats:
[cols=",,",options="header",]
|==========================================================
|Value/template |Legacy format output |TTCN-3 format output
|Unbound value |"<unbound>" |"-"
|Uninitialized template |"<uninitialized template>" |"-"
|Enumerated value |name (number) |name
|==========================================================
The "-" symbol is the NotUsedSymbol which can be used inside compound values, but when logging an unbound value which is not inside a record or record of the TTCN-3 output format of the logger is actually not a legal TTCN-3 value/template because a value or template cannot be set to be unbound. Thus this output format can be copy-pasted from a log file into a ttcn-3 file or to a module parameter value in a configuration file only if it semantically makes sense.
The C++ API extensions to change the logging format: +
A new enum type for the format in TTCN_Logger class:+
`enum data_log_format_t { LF_LEGACY, LF_TTCN }`; +
Static functions to get/set the format globally: +
`data_log_format_t TTCN_Logger::get_log_format();void` `TTCN_Logger::set_log_format(data_log_format_t p_data_log_format)`; +
A helper class to use a format until the end of the scope, when used as local variable. This can be used as follows: +
[source]
----
{
Logger_Format_Scope lfs(TTCN_Logger::LF_TTCN); // sets TTCN-3 log format
<log some values and templates>
} // end of scope -> the original format is restored
----
It is recommended to use this helper class because using directly the format setting functions of `TTCN_Logger` is more error prone, if the globally used logging format is not restored properly then log files might contain values/templates in a mixed/unexpected format.
=== Examples
The example below demonstrates the combined usage of buffered and unbuffered modes as well as the working mechanism of the event stack:
[source]
----
TTCN_Logger::begin_event(TTCN_DEBUG);
TTCN_Logger::log_event_str("first ");
TTCN_Logger::begin_event(TTCN_DEBUG);
TTCN_Logger::log_event_str("second ");
TTCN_Logger::log_str(TTCN_DEBUG, "third message");
TTCN_Logger::log_event_str("message");
TTCN_Logger::end_event();
TTCN_Logger::log_event_str("message");
TTCN_Logger::end_event();
----
The above code fragment will produce three lines in the log in the following order:
`third message`
`second message`
`first message`
If the code calls a C++ function that might throw an exception while the logger has an active event buffer care must be taken that event is properly finished during stack unwinding. Otherwise the stack of the logger and the call stack of the program will get out of sync. The following example illustrates the proper usage of buffered mode with exceptions:
[source]
----
TTCN_Logger::begin_event(TTCN_DEBUG);
try {
TTCN_Logger::log_event_str("something");
// a function is called from here
// that might throw an exception (for example TTCN_error())
TTCN_Logger::log_event_str("something else");
TTCN_Logger::end_event();
} catch (...) {
// don’t forget about the pending event
TTCN_Logger::end_event();
throw;
}
----
== Error Recovery during Test Execution
If a fatal error is encountered in the Test Port, you should call the function `TTCN_error` must be called to do the error handling. It has the following prototype in the Base Library:
[source, subs="+quotes"]
void TTCN_error(const char *fmt, …);
The parameter `fmt` contains the reason of the error in a NUL terminated character string in the format of a `printf` format string. If necessary, additional values should be passed to `TTCN_error` as specified in the format string. The error handling in the executable test program is implemented using C++ exceptions so the function `TTCN_error` never returns; instead, it throws an exception. The exception value contains an instance of the empty class called `TC_Error`. This exception is normally caught at the end of each test case and module control part. After logging the reason `TTCN_Logger::OS error()` is called. Finally, the verdict is set to error and the test executor performs an error recovery, so it continues the execution with the next test case.
It is not recommended to use own error recovery combined with the default method (that is, catching this exception).
== Using UNIX Signals
The UNIX signals may interrupt the normal execution of programs. This may happen when the program executes system calls. In this case, when the signal handler is finished the system call will fail and return immediately with an error code.
In the executable test program there are system calls not only in the Base Library, but in Test Ports as well. Since the other Test Ports that you are using may have been written by many developers, one cannot be sure that they are prepared to the effects of signals. So it is recommended to avoid using signals in Test Ports.
== Mixing C and C++ Modules
Modules written in C language may be used in the Test Ports. In this case the C header files must be included into the Test Port source code and the object files of the C module must be linked to the executable. Using a C compiler to compile the C modules may lead to errors when linking the modules together. This is because the C and C\++ compilers use different rules for mapping function names to symbol names of the object file to avoid name clashes caused by the C++ polymorphism. There are two possible solutions to solve this problem:
1. Use the same C++ compiler to compile all of your source code (including C modules).
2. If the first one is impossible (when using a third party software that is available in binary format only), the definitions of the C header file must be put into an `extern "C"` block like this.
[source]
----
#ifdef __cplusplus
extern "C" {
#endif
<... your C definitions ...>
#ifdef __cplusplus
};
#endif
----
The latter solution does not work with all C\++ compilers; it was tested on GNU C++ compiler only.
= References
1. link:https://www.etsi.org/deliver/etsi_es/201800_201899/20187301/04.05.01_60/es_20187301v040501p.pdf[Methods for Testing and Specification (MTS); The Testing and Test Control Notation version 3. Part 1: Core Language European Telecommunications Standards Institute ES 201 873-1 Version 4.5.1, April 2013]
2. Methods for Testing and Specification (MTS); The Testing and Test Control Notation version 3. Part 4: TTCN–3 Operational SemanticsEuropean Telecommunications Standards Institute. ES 201 873-4 Version 4.4.1, April 2012