= Test Ports
:table-number: 0
:toc:

The Java source code generated by the Java code generator is protocol independent, that is, it does not contain any device specific operations. To provide the connection between the executable test suite and SUT, that is, the physical interface of the test equipmentfootnote:[The test equipment not necessarily requires a special hardware; it can even be a simple PC with an Ethernet interface.], a so-called Test Port is needed.

The Test Port is a software library written in Java language, which is a part of the executable test program. It maps the device specific operations to function calls specified in an API. This chapter describes the Test Port API in details.

== Generating the Skeleton

The functions of Test Ports must be written by the user who knows the interface between the executable test suite and the test equipment. In order to make this development easier, Eclipse features can be used to generate and update Test Port skeletons. A Test Port belongs to one certain TTCN–3 port type, so the skeleton is generated based on port type definitions.

A Test Port consists of two parts. One part is generated automatically by the Java code generator, and it is put into the generated Java code. The user has nothing to do with this part.

The other part is a Java class, which is written mainly by the user. This class can be found in a separate Java file (their suffixes are `.java`). It is recommended to store this file in a folder separate from the generated java files (for example called `user_provided`), so as it should not be deleted when clearing the project.
The name of the source files and the Java class have to be identical to the name of the port type. And the Java class has to be located in the Java package whos name is generated as `org.eclipse.titan.` + projectname + `.user_provided`.
Please note that the name mapping rules described in <<12-mapping_ttcn3_data_types_to_java_constructs.adoc#mapping-of-names-and-identifiers, Mapping of Names and Identifiers>> also apply to these class and file names.

During the compilation, when the Java compiler encounters the usage of a Test Port that does not yet has a user generated implementation, it will report an error in the generated code for missing its import. Also offering Quick Fixes either by simply bringing the mouse cursor over the error location, or by right clicking and selecting Quick Fix from the menu. Using the action that starts like `Create class 'MyMessagePort' in package ...` eclipse will automatically generate the class the user needs.
Once the class is create one should set its base class and right click in its body part selecting the `Source`/`Override\Implement Methods...` to automatically generate a skeleton for the needed functions.

If the list of message types/signatures of a TTCN-3 port type changes, the list of the Test Port class member functions also needs to change. Java will report build error like "The typeXY must implement the inherited abstract method...". In this case, the `Override\Implement Methods...` action should be invoked again, to create the skeletons of the newly required functions.

If you have defined a TTCN–3 port type that you intend to use for internal communication only (that is, for sending and receiving messages between TTCN–3 test components), you do not need to generate and compile an empty Test Port skeleton for that port type. Adding the attribute with `{extension "internal"}` to the port type definition in the TTCN–3 module disables the generation and use of a Test Port for the port type.

In the following we introduce two port type definitions: one for a message based and another one for a procedure based port. In our further examples we will refer to the test port skeletons generated according to these definitions given within the project called `MyProject` and module called `MyModule`.

== Message-based Example

The definition of `MyMessagePort`:
[source]
----
type port MyMessagePort message
{
  in octetstring;
  out integer;
  inout charstring;
};
----
That is, the types integer and charstring can be sent, and octetstring and charstring can be received on port `MyMessagePort`.

The initial Test Port file (that is, `MyMessagePort.java`) will look as follows:
[source]
----
package org.eclipse.titan.MyProject.user_provided;

import org.eclipse.titan.MyProject.generated.MyModule.MyMessagePort_BASE;
import org.eclipse.titan.runtime.core.TitanCharString;
import org.eclipse.titan.runtime.core.TitanInteger;

public class MyMessagePort extends MyMessagePort_BASE {

	public MyMessagePort(final String name) {
		super(name);
	}

	@Override
	protected void outgoing_send(TitanInteger send_par) {
		// TODO Auto-generated method stub
	}

	@Override
	protected void outgoing_send(TitanCharString send_par) {
		// TODO Auto-generated method stub
	}
}
----

== Procedure-based Example

The definition of `MyProcedurePort` in module `MyModule`:
[source]
----
type port MyProcedurePort procedure
{
  in inProc;
  out outProc;
  inout inoutProc;
};
----

The signature definitions are imported from a module called `MyModule2`, `noblock` is not used and exceptions are used so that every member function of the port class is generated for this example. If the keyword `noblock` is used the compiler will optimize code generation by not generating outgoing reply, incoming reply member functions and their argument types. If the signature has no exception outgoing raise, incoming exception member functions and related types will not be generated.

The port type `MyProcedurePort` can handle `call`, `getreply` and `catch` operations referencing the signatures `outProc` and `inoutProc`, and it can handle `getcall`, `reply` and `raise` operations referencing the signatures `inProc` and `inoutProc`.

The initial Test Port file (that is, `MyProcedurePort.java`) will look as follows:

[source]
----
package org.eclipse.titan.MyProject.user_provided;

import org.eclipse.titan.MyProject.generated.MyModule.MyProcedurePort_BASE;
import org.eclipse.titan.MyProject.generated.MyModule2.inProc_reply;
import org.eclipse.titan.MyProject.generated.MyModule2.inoutProc_call;
import org.eclipse.titan.MyProject.generated.MyModule2.inoutProc_reply;
import org.eclipse.titan.MyProject.generated.MyModule2.outProc_call;

public class MyProcedurePort extends MyProcedurePort_BASE {

	public MyProcedurePort(final String name) {
		super(name);
	}

	@Override
	public void outgoing_call(outProc_call call_par) {
		// TODO Auto-generated method stub
	}

	@Override
	public void outgoing_call(inoutProc_call call_par) {
		// TODO Auto-generated method stub
	}

	@Override
	public void outgoing_reply(inProc_reply reply_par) {
		// TODO Auto-generated method stub
	}

	@Override
	public void outgoing_reply(inoutProc_reply reply_par) {
		// TODO Auto-generated method stub
	}
}
----


[[test-port-functions]]
== Test Port Functions

This section summarizes all possible member functions of the Test Port class. These functions have an empty implementation in the base class of the Test Port.

The identical functions of both port types are:

* the constructor

* the parameter setting function

* the map and unmap function

* the start and stop function

* descriptor event and timeout handler(s)

* some additional functions and attributes

The functions above will be described using an example of message based ports (`MyMessagePort`, also introducing the functions specific to message based port types). Using these functions is identical (or very similar) in procedure based Test Ports.

Functions specific to message based ports:

* send functions: outgoing send

* incoming functions: incoming message

* Functions specific to procedure based ports:

* outgoing functions: outgoing_call, outgoing_reply, outgoing_raise

* incoming functions: incoming_call, incoming_reply, incoming_exception

Both test port types can use the same logging and error handling mechanism, and the handling of incoming operations on port `MyProcedurePort` is similar to receiving messages on port `MyMessagePort` (regarding the event handler).

NOTE: The easiest way to discover what functions can be overwritten and to generate their skeleton is by using the earlier described `Override\Implement Methods...` functionality of eclipse. That functionality automatically list all functions from the class generated for the given testport and the its parent classes, that can be overwritten.

NOTE: Please note, that in Java functions by default inherit the documentation/comments from the function they overwrite. So while the functions just inserted to overwrite functions from the base class might not appear to have a comment, in eclipse moving the cursor over their name will reveal their actual comment.

=== Constructor

NOTE: On the Java side Test Ports do not have destructors.

The Test Port class belongs to a TTCN–3 port type, and its instances implement the functions of the port instances. That is, each Test Port instance belongs to the port of a TTCN–3 test component. The number of TTCN–3 component types, port types and port instances is not limited; you may have several Test Port classes and several instances of a given Test Port class in one test suite.

The Test Port instances are global and static objects from the point of view of the Java code. This means, their constructor is called before the test execution (that is, before the main function starts). They are also stored as threadlocal to be only accessible by the thread (Parallel Test Component) they belong to. The name of a Test Port object is composed of the name of the corresponding component type and the name of the port instance within the component type.

In case of parallel test execution, each TTCN–3 test component thread has its own Test Port instances. Of course, only the Test Ports of the active component type are used, the member functions of other inactive Test Port instances (except constructor) shall never be called. All Test Port instances should be handled as being static, their constructor is called only once, at the time their component is created. The test component threads (that is, the child threads of Host Controller) will have to create/initialize their own Test Port instances.

The Test Port class is derived from an abstract base class which can be found in the generated code. The base class implements, for instance, the queue of incoming messages.

The constructor takes one parameter containing the name of the port instance in a String. This string shall be passed further to the constructor of the base class as it can be found in the skeleton code. The default argument for the test port name is a null pointer, which is used when the test port object is a member of a port array.

WARNING: In case of port arrays the name of the test port is set after the constructor is completed. So the name of the test port should not be used in the constructor. The port name is always set correctly when any other member function is called.

=== Parameter Setting Function

Test Port parameters shall contain information which is independent from the TTCN-3 test suite. These values shall not be used in the test suite at all. You can define them as TTCN–3 constants or module parameters, but these definitions are useless and redundant, and they must always be present when the Test Port is used.

For instance, using Test Port parameters can be used to convey configuration data (that is, some options or extra information that is necessary for correct operation) or lower protocol layer addresses (for example, IP addresses).

Test Port parameters shall be specified by the user of executable tests in the `[TESTPORT_PARAMETERS]` section of the run-time configuration file (see section `[TESTPORT_PARAMETERS]` in link:https://gitlab.eclipse.org/eclipse/titan/titan.core/tree/master/usrguide/referenceguide[Programmer's Technical Reference]). The parameters are maintained for each test port instance separately; wildcards can be used as well. In the latter case the parameter is passed to all Test Port matching the wildcard.

Each Test Port parameter must have a name, which must be unique within the Test Port only. The name must be a valid identifier, that is, it must begin with a letter and must contain alphanumerical characters only.

All Test Port parameter values are interpreted by the test executor as character strings. Quotation marks must be used when specifying the parameter values in the configuration file. The interpretation of parameter values is up to you: you can use some of them as symbolic values, numbers, IP addresses or anything that you want.

Before the test execution begins, all parameters belonging to the Test Port are passed to the Test Port by the runtime environment of the test executor using the function `set_parameter`. The default implementation of this function does nothing and ignores all parameters.

Each parameter is passed to the Test Port one-by-one separatelyfootnote:[If the same parameter of the same port instance is specified several times in the configuration file, the function `set_parameter` will also be called several times.], the two arguments of `set_parameter` contain the name and value of the corresponding parameter, respectively, in Strings.

It is warmly recommended that the Test Port parameter handling functions be fool-proof. For instance, the Test Port should produce a proper error message (for example by calling `TtcnError`) if a mandatory parameter is missing instead of causing unreliable behavior later. Repeated setting of the same parameter should produce warnings for the user (for example by using the function `TtcnError.TtcnWarning`) and not memory leaks.

NOTE: On the MTC, in both single and parallel modes, the handling of Test Port parameters is a bit different from that on PTCs. The parameters are passed only to active ports, but the component type of MTC (thus the set of active ports) depends on the `runs on` clause of the test case that is currently being executed. It would be difficult for the runtime environment to check at the beginning of each test case whether the corresponding MTC component type has already been active during a previous test case run. Therefore all Test Port parameters belonging to the active ports of the MTC are passed to the `set_parameter` function at the beginning of every test case. The Test Ports of MTC shall be prepared to receive the same parameters several times (with the same values, of course) if more than one test case is being executed.

If system related Test Port parameters are used in the run-time configuration file (that is, the keyword `system` is used as component identifier), the parameters are passed to your Test Port during the execution of TTCN–3 `map` operations, but before calling your `user_map` function. Please note that in this case the port identifier of the configuration file refers to the port of the test system interface that your port is mapped to and not the name of your TTCN–3 port.

The name and exact meaning of all supported parameters must be specified in the user documentation of the Test Port.

=== Map and Unmap Functions

The run-time environment of the TTCN–3 executor knows nothing about the communication towards SUT, thus, it is the user’s responsibility to establish and terminate the connection with SUT. The TTCN–3 language uses two operations to control these connections, `map` and `unmap`.

For this purpose, the Test Port class provides two member functions, `user_map` and `user_unmap`. These functions are called by the test executor environment when performing TTCN–3 `map` and `unmap` operations, respectively.

The `map` and `unmap` operations take two pairs of component references and ports as arguments. These operations are correct only if one of the arguments refer to a port of a TTCN–3 test component while the other port corresponds to SUT. This aspect of correctness is verified by the run-time environment, but the existence of a system port is not checked.

The port names of the system are converted to Strings and passed to functions `user_map` and `user_unmap` as parameters. Unlike other identifiers, the underscore characters in these port names are not translated.

NOTE: in TTCN–3 it is not allowed to map a test component port to several system ports at the same time. The run-time environment, however, is not so strict and allows this to handle transient states during configuration changes. In this case messages can not be sent to SUT even with explicit addressing, but the reception of messages is permitted. When putting messages into the input queue of the port, it is not important for the test executor (even for the TTCN–3 language) which port of the system the message is received from.

The execution of TTCN–3 test component that requested the mapping or unmapping is suspended until your `user_map` or `user_unmap` functions finish. Therefore it is not allowed to block unnecessarily the test execution within these functions.

When the Test Port detects an error situation during the establishment or termination of the physical connection towards the SUT, the function `TTCN_error` shall be used to indicate the failure. If the error occurs within `user_map` the run-time environment will assume that the connection with SUT is not established thus it will not call `user_unmap` to destroy the mapping during the error recovery procedure. If `user_map` fails, it is the Test Port writer’s responsibility to release all allocated resources and bring the object variables into a stable state before calling `TtcnError`. Within `user_unmap` the errors should be handled in a more robust way. After a minor failure it is better to issue a warning and continue the connection termination instead of panicking. `TtcnError` shall be called only to indicate critical errors. If `user_unmap` is interrupted with an error the run-time environment assumes that the mapping has been terminated, that is, `user_unmap` will not be called again.

NOTE: if either `user_map` or `user_unmap` fails, the error is indicated on the initiator test component as well; that is, the respective map or `unmap` operation will also fail and error recovery procedure will start on that component.

==== Parameters of the Map and Unmap Functions

Parameters can be sent to the `user_map` and `user_unmap` functions from TTCN-3 code using the `param` clause of the `map` and `unmap` operations.

The `user_map` and `user_unmap` functions have a parameter of type `Map_Params`, which contains the string representations of the `in` and `inout` parameters of the `map`/`unmap` operation. The string representations of `out` parameters are empty strings (as these are considered as being `unbound` at the beginning of the `map`/`unmap` operation). After the `user_map` or `user_unmap` function ends and the mapping/unmapping is concluded, the final values (string representations) of `out` and `inout` parameters in the `Map_Params` object are sent back to the mapping/unmapping requestor.

The following member functions can be used to obtain or set data in the `Map_Params` object:

[source]
----
public int get_nof_params()
----
Returns the number of parameters in the object. This will either be zero (if the `map` or `unmap` operation had no `param` clause) or the number of parameters specified in the system port type definition's `map param` or `unmap param` clause.

[source]
----
public TitanCharString get_param(final int index)
----
Returns the string representation of the parameter at index `p_index`. This method shall be used to retrieve the values of `in` and `inout` parameters. The parameter indices start at 0. The order of the parameters is the same as their order of declaration. Default values of parameters are automatically set by the runtime environment before the `user_map`/`user_unmap` call. The string representations retrieved with this function can be converted back to the parameter's TTCN-3 type with the predefined function `string_to_ttcn`.

[source]
----
public void set_param(final int index, final TitanCharString param)
----
Sets the string representation of the parameter at index `p_index` to the string `p_param`. This method shall be used to set the final values of `out` and `inout` parameters. The string representation of a TTCN-3 value can be obtained using the predefined function `ttcn_to_string`. If the final value of an `out` or `inout` parameter is an empty string, then the variable used as parameter will remain unchanged. Otherwise its new value will be calculated by applying `string_to_ttcn` on the string value set in the `user_map` or `user_unmap` function (this could cause dynamic test case errors if the string representation is invalid).

Usage example:

Port type:
[source]
----
type port MyPort message {
  ...
  map param(in MyInParType in_par, inout MyInOutParType inout_par, out MyOutParType out_par)
}
----
`user_map` function in port implementation:
[source]
----
@Override
protected void user_map(final String system_port, final Map_Params params) {
  if (params.get_nof_params() == 0) {
    // there were no map parameters

    // do mapping
    ...
  } else {
    // there were map parameters

    // extract 'in' and 'out' parameters
    MyInParType in_par = new MyInParType();
    TitanCharString.string_to_ttcn(params.get_param(0), in_par);
    MyInOutParType inout_par = new MyInOutParType();
    TitanCharString.string_to_ttcn(params.get_param(1), inout_par);
    MyOutParType out_par = new MyOutParType(); // remains unbound

    // do mapping
    ...

    // update 'out' and 'inout' parameters
    params.set_param(1, TitanCharString.ttcn_to_string(inout_par));
    params.set_param(2, TitanCharString.ttcn_to_string(out_par));
  }
}
----

=== Start and Stop Functions

The Test Port class has two member functions: `user_start` and `user_stop`. These functions are called when executing `port start` and `port stop` operations, respectively. The functions have no parameters and return types.

These functions are called through a stub in the base class, which registers the current state of the port (whether it is started or not). So `user_start` will never be called twice without calling `user_stop` or vice versa.

All ports of test components are started implicitly immediately after creation. Operations put in a `user_start` function must not be blocking the execution for a longer period. This not only hangs the new PTC but the also component that performed the `create` operation (usually the MTC). All ports are stopped at the end of test cases or at PTC termination, even if `stop` statements are missing.

In functions `user_start` and `user_stop` the device should be initialized or shut down towards SUT (that is, the communications socket). Also the event handler should be installed or uninstalled (see later).

=== Outgoing Operations

Outgoing operations are `send` (specific to message based ports); `call`, `reply`, and `raise` (specific to procedure based ports).

==== Send Functions

The Test Port class has an overloaded function called `outgoing_send` for each outgoing message type. This function will be called when a message is sent on the port and it should be routed to the system (that is, SUT) according to the addressing semanticsfootnote:[That is, the port has exactly one mapping and either the port has no connections or the message is explicitly addressed by a `send (…) to system` statement.] of TTCN–3. The messages (implicitly or explicitly) addressed to other test components are handled inside the test executor; the Test Ports have nothing to do with them. The function `outgoing_send` will be also called if the port has neither connections nor mappings, but a message is sent on it.

The only parameter of `outgoing_send` contains a read-only reference to the message in the internal data representation format of the test executor. The access methods for internal data types are described in <<12-mapping_ttcn3_data_types_to_java_constructs.adoc#predefined-ttcn-3-data-types, Predefined TTCN–3 Data Types>>. The test port writer should encode and send the message towards SUT. For information on how to use the standard encoding functions like RAW, please consult the earlier chapters of this document. Sending a message on a not started port causes a dynamic test case error. In this case `outgoing_send` will not be called.

==== Call, Reply and Raise Functions

The procedure based Test Port class has overloaded functions called `outgoing_call`, `outgoing_reply` and `outgoing_raise` for each `call`, `reply` and `raise` operations, respectively. One of these functions will be called when a port-operation is addressing the system (that is, SUT using the to `system` statement).

The only parameter of these functions is an internal representation of the signature parameters (and possibly its return value) or the exceptions it may raise. The signature classes are described in <<12-mapping_ttcn3_data_types_to_java_constructs.adoc#using-the-signature-classes,Using the Signature Classes>>.

=== Incoming Operations

Incoming operations are `receive` for incoming messages (specific to message based ports); `call`, `reply` and `raise` for signatures (specific to procedure based ports).

==== Descriptor Event and Timeout Handlers

The handling of incoming messages (or operations) is more difficult than sending. The executable test program has two states. In the first state, it executes the operations one by one as specified in the test suite (for example, it evaluates expressions, calls functions, sends messages, etc.). In the other state it waits for the response from SUT or for a timer to expire. This happens when the execution reaches a blocking statement, that is, one of a stand-alone `receive`, `done`, `timeout` statements or an `alt` construct.

After reaching a blocking statement, the test executor evaluates the current snapshot of its timer and port queues and tries to match it with the reached statements and templates. If the matching fails, the executor sleeps until something happens to its timers or ports. After waking up, it re-evaluates its snapshot and tries to match it again. The last two steps are repeated until the executor finds the first matching statement. If the test executor realizes that its snapshot can never match the reached TTCN–3 statements, it causes a dynamic test case error. This mechanism prevents it from infinite blocking.

The test executor handles its timers itself, but it does not know anything about the communication with SUT. So each Test Port instance should inform the snapshot handler of the executor what kind of event the Test Port is waiting for. The event can be either the reception of data on one or more socket channels or a timeout (when polling is used) or both of them.

When the test executor reaches a blocking statement and any condition – for which the Test Port waits – is fulfilled, the event handler will be called. First one has to get the incoming message or operation from the operating system. After that, one has to decode it (and possibly decide its type). Finally, if the internal data structure is built, one has to put it into the queue of the port. This can be done using the member function `incoming_message` if it is a message, and using `incoming_call`, `incoming_reply` or `incoming_exception` if it is an operation.

The execution must not be blocked in event handler functions; these must return immediately when the message or operation processing is ready. In other words, always use non-blocking calls. In the case when the messages are fragmented (for instance, when testing TCP based application layer protocols, such as HTTP), intermediate buffering should be performed in the Test Port class.

===== Event and timeout handling interface

To be notified about available events the `Handle_Event` function has to be implemented.
[source, subs="+quotes"]
public void Handle_Event(final SelectableChannel channel, final boolean is_readable, final boolean is_writeable);

Using `Handle_Event` allows receiving all events of a descriptor in one function call.

The first parameter in all of these functions is the selectable channel. The second is true if the channel is readable. The third is true if it is writeable.

You can install or uninstall the event handler by calling the following inherited member functions:
[source, subs="+quotes"]
protected void Install_Handler(final Set<SelectableChannel> read_channels, final Set<SelectableChannel> write_channels, final double call_interval) throws IOException;
protected void Uninstall_Handler() throws IOException;

`Install_Handler` installs the event handler according to its parameters. It takes three arguments, two sets of SelectableChannels and a timeout value. Some of the parameters can be ignored, but ignoring all at the same time is not permitted.

`read_channels` is the set of SelectabeChannel to register the handler for reading. If null the handler is not registered for any channel to handle reading.
`write_channels` is the set of SelectabeChannel to register the handler for writing. If null the handler is not registered for any channel to handle writing.

The call interval value is measured in seconds. It means that the event handler function will be called when the time elapsed since its last call reaches the given value. This parameter is ignored when its value is set to zero or negative.

If you want to change your event handling parameters, you may simply call the function `Install_Handler` again (calling of `Uninstall_Handler` is not necessary).

`Uninstall_Handler` will uninstall your previously installed event handler. The `stop` port operation also uninstalls the event handler automatically. The event handler may be installed or uninstalled in any Test Port member function, even in the event handler itself.

==== Receiving messages

The member function `incoming_message` of message based ports can be used to put an incoming message in the queue of the port. There are different functions for each incoming message type. These functions are inherited from the base class. The received messages are logged when they are put into the queue and not when they are processed by the test suitefootnote:[Note that if the port has connections as well, the messages coming from other test components will also be inserted into the same queue independently from the event handler.].

In our example the class `MyMessagePort_BASE` has the following member functions:
[source, subs="+quotes"]
protected void incoming_message(final TitanOctetString incoming_par);
protected void incoming_message(final TitanCharString incoming_par);

==== Receiving calls, replies and exceptions

Receiving operations on procedure based ports is similar to receiving messages on message based ports. The difference is that there are different overloaded incoming functions for call, reply and raise operations called `incoming_call`, `incoming_reply` and `incoming_exception`, respectively. The event handler (when called) must recognize the type of operation on receiving and call one of these functions accordingly with one of the internal representations of the signature (see <<12-mapping_ttcn3_data_types_to_java_constructs.adoc #additional-non-standard-functions, Additional Non-Standard Functions>>).

In the examplefootnote:[In the example the signatures were defined in a different TTCN–3 module named MyModule2, as a consequence all types defined in that module must be prefixed with the Java name of that module and its class be imported.] the class `MyProcedurePort_BASE` has the following member functions for incoming operations:
[source]
----
protected void incoming_call(final MyModule2.inProc_call incoming_par);
protected void incoming_call(final MyModule2.inoutProc_call incoming_par);
protected void incoming_reply(final MyModule2.outProc_reply incoming_par);
protected void incoming_reply(final MyModule2.inoutProc_reply incoming_par);
protected void incoming_exception(final MyModule2.outProc_exception incoming_par);
protected void incoming_exception(final MyModule2.inoutProc_exception incoming_par);
----
For example, if the event handler receives a call operation that refers to the signature called `inoutProc`, it has to fill the parameters of an instance of the class `inoutProc_call` with the received data. Then it has to call the function `incoming_call` with this object to place the operation into the queue of the port.

The following table shows the relation between the direction of the message type or signature in the port type definition and the incoming/outgoing functions that can be used. `MyPort` in the table header refers to `MyMessagePort` or `MyProcedurePort` in the example depending on the type of the port (message based or procedure based).

.Outgoing and incoming operations

[cols=" ",options="header",]
|===
| | 4+^.^|`MyPort.outgoing_` 4+^.^| `MyPort_BASE.incoming_`
| | |send |call |reply |raise |message |call |reply |exception
.3+^.^|message type |in |○ |○ |○ |○ |● |○ |○ |○
|out |● |○ |○ |○ |○ |○ |○ |○
|inout |● |○ |○ |○ |● |○ |○ |○
.3+^.^|signature |in |○ |○ |● |● |○ |● |○ |○
|out |○ |● |○ |○ |○ |○ |● |●
|inout |○ |● |● |● |○ |● |● |●
|===

● supported

○ not supported

=== Additional Functions and Attributes

Any kind of attributes or member functions may be added to the Test Port. A selectable channel, which you communicate on, is almost always necessary. Names not interfering with the identifiers generated by the Java code generator can be used in the java file (for example, the names containing one underscore character). Avoid using static variables because it can be very confusing when more than one instances of the Test Port run simultaneously. Any kind of software libraries may be used in the Test Port as well.

In addition, the following `protected` attributes of ancestor classes are available:

.Protected attributes

[width="100%",cols="34%,33%,33%",options="header",]
|======================================================================================================
|Name ^.^|Type |Meaning
|`is_active` ^.^|boolean |Indicates whether the Test Port is active.
|`is_started` ^.^|boolean |Indicates whether the Test Port is started.
|`is_halted` ^.^|boolean |Indicates whether the Test Port is halted.
|`port_name` ^.^|String |Contains the name of the Test Port instance.
|======================================================================================================

Underscore characters are not duplicated in port_name. In case of port array member instances the name string looks like this: `"Myport_array[5]"`.

== Support of `address` Type

The special user-defined TTCN–3 type `address` can be used for addressing entities inside the SUT on ports mapped to the `system` component. Since the majority of Test Ports does not need TTCN–3 addressing and in order to keep the Test Port API backward compatible the support of `address` type is disabled by default. To enable addressing on a particular port type the extension attribute `"address"` must be added to the TTCN–3 port type definition. In addition to component references this extension will allow the usage of `address` values or variables in the `to` or `from` clauses and `sender` redirects of port operations.

In order to use addressing, a type named `address` shall be defined in the same TTCN–3 module as the corresponding port type. Address types defined in other modules of the test suite do not affect the operation of the port type. It is possible to link several Test Ports that use different types for addressing SUT into the same executable test suite.

Test Ports that support SUT addressing have a slightly different API, which is considered when generating Test Port skeleton. This section summarizes only the differences from the normal API.

In the communication operations the test port author is responsible for handling the address information associated with the message or the operation. In case of an incoming message or operation the value of the received address will be stored in the port queue together with the received message or operation.

The generated code for the port skeleton of message based ports will be the same, except `outgoing_send` member function, which has an extra parameter pointing to an `TitanAddress` value. With the example given in <<test-port-functions, Test Port Functions>>:
[source]
----
void outgoing_send(final TitanInteger send_par, final TitanAddress destination_address);
void outgoing_send(final TitanCharString send_par, final TitanAddress destination_address);
----

NOTE: when the type named `address` is defined as a synonym of an other type, these functions could also report that type to be the type of the `destination_address` formal parameter.

If an `address` value was specified in the `to` clause of the corresponding TTCN–3 `send` operation the second argument of `outgoing_send` points to that value. Otherwise it is set to the `NULL` pointer. The Test Port code shall be prepared to handle both cases.

The outgoing operations of procedure based ports are also generated in the same way if the `address` extension is specified. These functions will also have an extra parameter. Based on our example, these will have the following form:
[source]
----
void outgoing_call(final MyModule2.outProc_call call_par, final TitanAddress destination_address);
void outgoing_call(final MyModule2.inoutProc_call call_par, final TitanAddress destination_address);
void outgoing_reply(final MyModule2.inProc_reply reply_par, final TitanAddress destination_address);
void outgoing_reply(final MyModule2.inoutProc_reply reply_par, final TitanAddress destination_address);
void outgoing_raise(final MyModule2.inProc_exception raise_exception, final TitanAddress destination_address);
void outgoing_raise(final MyModule2.inoutProc_exception raise_exception, final TitanAddress destination_address);
----

The other difference is in the `incoming_message` member function of class `MyMessagePort_BASE`, and in the incoming member functions of class `MyProcedurePort_BASE`. These have an extra parameter, which is a pointer to an `TitanAddress` value. The version of the function that does not have this formal parameter, will call this function with a null value passed as the sender_address. In our example of `MyMessagePort_BASE`:
[source]
----
void incoming_call(final MyModule2.inProc_call incoming_par, final int sender_component, final TitanAddress sender_address);
void incoming_call(final MyModule2.inoutProc_call incoming_par, final int sender_component, final TitanAddress sender_address);
void incoming_reply(final MyModule2.outProc_reply incoming_par, final int sender_component, final TitanAddress sender_address)
void incoming_reply(final MyModule2.inoutProc_reply incoming_par, final int sender_component, final TitanAddress sender_address)
void incoming_exception(final MyModule2.outProc_exception incoming_par, final int sender_component, final TitanAddress sender_address)
void incoming_exception(final MyModule2.inoutProc_exception incoming_par, final int sender_component, final TitanAddress sender_address)
----

If the event handler of the Test Port can determine the source address where the message or the operation is coming from, it shall pass a pointer to the incoming function, which points to a variable that stores the `address` value. The given address value is not modified by the run-time environment and a copy of it is created when the message or the operation is appended to the port queue. If the event handler is unable to determine the sender address the default null value shall be passed as the argument.

The address value stored in the port queue is used in `receive`, `trigger`, `getcall`, `getreply`, `catch` and `check` port operations: it is matched with the `from` clause and/or stored into the variable given in the `sender` redirect. If the receiving operation wants to use the address information of the first element in the port queue, but the Test Port has not supplied it a dynamic testcase error will occur.

== Provider Port Types

Test Ports that belong to port types marked with `extension` attribute `"provider"` have a slightly different API. Such port types are used to realize dual-faced ports, the details of which can be found in section "Dual-faced ports" in the link:https://gitlab.eclipse.org/eclipse/titan/titan.core/tree/master/usrguide/referenceguide[Programmer's Technical Reference].

The purpose of this API is to allow the re-use of the Test Port class with other port types marked with attribute `user` or with ports with translation capability (link:https://www.etsi.org/deliver/etsi_es/202700_202799/202781/01.04.01_60/es_202781v010401p.pdf[Methods for Testing and Specification (MTS); The Testing and Test Control Notation version 3; TTCN-3 Language Extensions: Configuration and Deployment Support]). The user port types may have different lists of incoming and outgoing message types. The transformations between incoming and outgoing messages, which are specified entirely by the attribute of the user port type, are done independently of the Test Port. The Test Port needs to support the sending and reception of message types that are listed in the provider port type.

The provider port can be accessed through the port which maps to the port with provider attribute. The `get_provider_port()` is a member function of the TitanPort class:
[source, subs="+quotes"]
TitanPort get_provider_port();

This function is useful when a reference to the provider type is needed. It returns the provider port type for user ports and ports with translation capability. Otherwise returns null. The function causes dynamic testcase error when the port has more than one mapping, or the port has both mappings and connections. The function’s return value must be manually cast to the correct provider port type.

This section summarizes only the differences from the normal Test Port API:

* The name of the Test Port class is suffixed with the string `_PROVIDER` (for example `MyMessagePort_PROVIDER` instead of `MyMessagePort`).

* The base class of the Test Port is class `TitanPort`, which is part of the Base Library. Please note that normal Test Ports are also derived from class TitanPort, but indirectly through an intermediate class with suffix `_BASE`.

* The member functions that handle incoming messages and procedure-based operations (that is `incoming_message`, `incoming_call`, `incoming_reply` and `incoming_exception`) must be defined as override-able functions. These functions will be implemented in various descendant classes differently.

* The member functions of the Test Port may refer to Java classes that are generated from user-defined message types and signatures.

The following example shows the skeleton of a provider port type Test Port.

Port type definition in TTCN–3 :
[source]
----
type port MyProviderPort mixed {
  inout MyMessage, MySignature;
} with { extension "provider" }
----

Source file `MyProviderPort_PROVIDER.java`:
[source]
----
package org.eclipse.titan.MyProject.user_provided;

import java.nio.channels.SelectableChannel;

import org.eclipse.titan.MyProject.generated.MyModule.MyMessage;
import org.eclipse.titan.MyProject.generated.MyModule.MySignature_call;
import org.eclipse.titan.MyProject.generated.MyModule.MySignature_exception;
import org.eclipse.titan.MyProject.generated.MyModule.MySignature_reply;
import org.eclipse.titan.runtime.core.TitanPort;

public class MyProviderPort_PROVIDER extends TitanPort {

	public MyProviderPort_PROVIDER() {
		super();
	}

	public MyProviderPort_PROVIDER(final String name) {
		super(name);
	}

	@Override
	public void set_parameter(final String parameter_name, final String parameter_value) {
	}

	@Override
	public void Handle_Event(final SelectableChannel channel, final boolean is_readable,
			final boolean is_writeable) {
	}

	@Override
	protected void user_map(final String system_port, final Map_Params params) {
	}

	@Override
	protected void user_unmap(final String system_port, final Map_Params params) {
	}

	@Override
	protected void user_start() {
	}

	@Override
	protected void user_stop() {
	}

	public void outgoing_send(final MyMessage send_par) {
	}
	public void outgoing_call(final MySignature_call call_par) {
	}
	public void outgoing_reply(final MySignature_reply reply_par) {
	}
	public void outgoing_raise(final MySignature_exception raise_Exception) {
	}
}
----

== Tips and Tricks

The following sections deal with logging and error handling in Test Ports.

=== Logging

Test Ports may record important events in the Test Executor log during sending/receiving or encoding/decoding messages. Such log messages are also good for debugging fresh code.

The Test Port member functions may call the functions of class `TTCN_Logger`.
These functions are detailed in <<13-tips_&_troubleshooting.adoc#logging-in-test-ports-or-external-functions, Logging in Test Ports or External Functions>>.

If there are many points in the Test Port code that want to log something, it can be a good practice to write a common log function in the Test Port class. We show here an example where the calling of `log` uses Java's MessageFormat.format to create a custom message, and inside the `log` function TTCN_Logger.log_event demonstrates logging using the standard C function `printf` style and forwards the message to the Test Executor’s logger:

[source]
----
private void value_logging(final TitanInteger i) {
  log(MessageFormat.format("The value of i : {0}.", i.get_int()));
}

private void log(final String content) {
  TTCN_Logger.begin_event(Severity.DEBUG_USER);
  TTCN_Logger.log_event("Example Test Port (%s): ", get_name());
  TTCN_Logger.log_event_str(content);
  TTCN_Logger.end_event();
}
----

=== Error Handling

None of the Test Port member functions have return value like a status code. If a function returns normally, the run-time environment assumes that it has performed its task successfully. The handling of run-time errors is done using Java exceptions. This simplifies the program code because the return values do not have to be checked everywhere and dynamically created complex error messages can be used if necessary.

If any kind of fatal error is encountered anywhere in the Test Port, an exception of type `TtcnError` should be thrown:
[source, subs="+quotes"]
throw new TtcnError(errorMessage);

Its parameter should contain the description of the error in a String. The exception is usually caught at the end of the test case or PTC function that is being executed. In case of error, the verdict of the component is set to `error` and the execution of the test case or PTC function terminates immediately.

The error string is written into the log file by `TtcnError` immediately. Such type of exception should never be caught or thrown directly. If you want to implement your own error handling and error recovery routines you had better use your own classes as exceptions.

If you write your own error reporting function you can add automatically the name of the port instance to all of your error messages. This makes the fault analysis for the end-users easier. In the following example the error message will occupy two consecutive lines in the log since we can pass only one format string to `TtcnError`.
[source]
----
private void error(final String content) {
		TTCN_Logger.begin_event(Severity.ERROR_UNQUALIFIED);
		TTCN_Logger.log_event("Example Test Port (%s): ", get_name());
		TTCN_Logger.log_event_str(content);
		TTCN_Logger.end_event();
		throw new TtcnError(MessageFormat.format("Fatal error in Example Test Port {0} (see above).", get_name()));
	}
----

There is another function for denoting warnings (that is, events that are not so critical) with the same parameter list as TtcnError:
[source, subs="+quotes"]
void TtcnError.TtcnWarning(warningMessage);

This function puts an entry in the executor’s log with severity `TTCN_WARNING`. In contrast to `TtcnError`, after logging the given message `TtcnWarning` returns and your test port can continue running.

== Setting timestamps

In order to use the timestamp redirects (`-> timestamp`) described in chapter 5 of the TTCN-3 standard extension `TTCN-3 Performance and Real Time Testing` (ETSI ES 202 782 V1.3.1, <<14-references.adoc#_16, [16]>>) the test port writer needs to add extra code to set the timestamps for the incoming and outgoing port operations of each port with the `realtime` clause.

=== Incoming operations

The timestamps of incoming port operations (`receive`, `trigger`, `getcall`, `getreply`, `catch` and `check`) need to be set when the incoming message or procedure is added to the queue.

The member functions `incoming_message`, `incoming_call`, `incoming_reply` and `incoming_exception` (which add the message/procedure to the queue) have an optional `TitanFloat` parameter called `timestamp`, if the test port was declared with the `realtime` clause.

The value given to this parameter will be the one stored in the variable referenced in the timestamp redirect, if the operation has a timestamp redirect (otherwise the value is ignored).

It is recommended that this parameter be set to the current test system time, which can be queried with `TTCN_Runtime.now();`, or to a float variable that was set to the current test system time earlier in the function.

Examples:
[source]
----
incoming_message(my_message, TTCN_Runtime.now());
----

[source]
----
TitanFloat reply_time = TTCN_Runtime.now();

...

incoming_reply(my_reply, reply_time);
----

=== Outgoing operations

The timestamps of outgoing port operations (`send`, `call`, `reply`, `raise`) need to be set in the member functions `outgoing_send`, `outgoing_call`, `outgoing_reply` and `outgoing_raise`.

These functions have a `TitanFloat` pointer parameter called `timestamp_redirect`, if the test port was declared with the `realtime` clause.

The value pointed to by this parameter will be the one stored in the variable referenced in the timestamp redirect, if the operation has a timestamp redirect.

If it does not have a timestamp redirect, then this value parameter will be null. Because of this, the parameter must always have a null check before it is assigned a value.

It is recommended that the value pointed to by the parameter be set to the current test system time, which can be queried with `TTCN_Runtime.now()`.

Example:
[source]
----
if (timestamp_redirect != null) {
	timestamp_redirect.operator_assign(TTCN_Runtime.now());
}
----

NOTE: Because of this extra parameter, adding or removing the `realtime` clause from a port will cause already-written Java code for the port to no longer compile. In these cases the new parameters must be manually added or removed from the mentioned functions.
