Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Titan » Synchronization between independent events
Synchronization between independent events [message #1764639] Thu, 01 June 2017 06:31
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Dear all,

The executing TTCN-3 code is an isolated universe consisting of an MTC (Main Test Component) and a number of (0 to n) PTCs (Parallel Test Components) communicating with the external world using a small number of restricted communication channels (test ports, logging interface etc.)
This helps keeping the code abstract, on the other hand explains why there are no language elements to communicate directly with the underlying operation system.

The PTCs once spawned act totally independent from the MTC (apart from a system crash of course); there is no default mechanism to exchange information between the MTC or PTCs, or between PTCs themselves.
However, such a feedback is often needed: for the sake of example let's assume that MTC is building up a call over a telecom network (or simulating some such) and starts a check over a PTC simulating the charging to verify the call is covered.
The function started over the PTC will execute but it has no possibility to return the result.

Communication channels, if needed, will have to be provisioned by the user. These channels will permit synchronizing independent events in this abstract universe of TTCN-3. The MTC usually acts as a conductor for the orchestra of PTCs created, as it has the privilege of being able to create or end PTCs.

These channels usually appear as simple message ports that connect MTC to PTCs. Synchronous blocking ports can also be used, but non-blocking message ports offer more flexibility (as execution is not halted when waiting for reply).

By the way, some wrongly believe exchange of information between components should be solved by global variables. If there were global variables , then the sender component could just write a message into such a variable, and the receiver could instantly access it.
I have been part of several debates where it was argued that TTCN-3 lacks global variables and these should be added to the standard.
Global variables correspond to a model of universe where information propagates with infinite speed, or put otherwise, the speed of light is infinite. This may distort the simulation to a point where the results are falsified, so please, let's stick to synchronization ports, although they may appear to complicate things.
One may say that we should leave usage ( or rather non-usage) of global variables to the self-restraint of programmers but self-restraint is an art only the greatest can master and I must say is quite rare among programmers. Lack of global variables is not an overlook, it's deliberate.

To exemplify the use of sync channels I will used the weathered example of SNMP over UDP which apparently throws an error when run in virtual machines.

The original code can be downloaded from this post:
Example of SNMP over UDP(Example of SNMP over UDP with ASN.1 and dual-faced test port)
https://www.eclipse.org/forums/index.php/t/1068184/

The link to the code archive:
https://www.eclipse.org/forums/index.php?t=getfile&id=22414&


The reason for the error is twofold: first of all , it appears that map is executing slower on virtual machines then on physical machines (the details are yet to be investigated)
and secondly, improper synchronization between MTC and the echoing PTC.

To reproduce the error (in case it does not appear on your machine, as it did not manifest itself on mine) let's insert a 100 ms delay before the map execution on the PTC:


function f_echo() runs on Echo_SNMP_CT
{  

      var ASP_UDP         v_ASP_UDP_r, v_ASP_UDP 
     
     timer T0 := 0.1; 
     T0.start;
     T0.timeout;

   map(self:UDP_PCO, system:UDP_PCO);
:
:


What happens now is that the PTC is created and f_echo is started on it , but execution continues on MTC and a message is sent to PTC before the UDP port would be mapped.
The PTC has no chance to answer so the "alt" waiting for reply times out , the verdict defaults to fail.



2017/May/31 08:27:22.078301 PORTEVENT SNMP_Test2.ttcn:212 Sent on UDP_PCO_DF to system @SNMPmsg-Types.SNMPv1-Message : { version := 0, community := '7075626C6963'O ("public"), data := { get_request := { request_id := 5, error_status := 1, error_index := 1, variable_bindings := { } } } }
2017/May/31 08:27:22.078400 PORTEVENT SNMP_Test2.ttcn:212 Outgoing message was mapped to @UDPasp_Types.ASP_UDP_message : { data := '301802010004067075626C6963A00B0201050201010201013000'O, remote_addr := "127.0.0.1", remote_port := 35000, id := 0 }
2017/May/31 08:27:22.078455 TIMEROP SNMP_Test2.ttcn:214 Start timer T: 5 s
2017/May/31 08:27:27.078516 TIMEROP SNMP_Test2.ttcn:223 Timeout T: 5 s
2017/May/31 08:27:27.078584 VERDICTOP SNMP_Test2.ttcn:223 setverdict(fail): none -> fail	





	
testcase tc_SNMP_1()runs on Test_SNMP_CT
{
  var Echo_SNMP_CT v_echo_CT := Echo_SNMP_CT.create alive;  
  timer T := 5.0;
  
  v_echo_CT.start(f_echo())

  map(self:UDP_PCO_DF, system:UDP_PCO_DF);
  var integer v_Id := f_Test_openConnection(tsp_connectionParams,-1);  

//SNMP V1
  UDP_PCO_DF.send(t_snmp_v1_getrequest_msg(5,{}));
 
  T.start;
  alt 
  {
    []UDP_PCO_DF.receive(t_snmp_v1_getrequest_msg(5,{}))
      {setverdict(pass);T.stop;} 
         
    []UDP_PCO_DF.receive
      {setverdict(fail);T.stop;v_echo_CT.stop;stop} 
       
    [] T.timeout {setverdict(fail);v_echo_CT.stop;stop}              
  }	
:
:




         MTC                           PTC

            +
            |      create
            +---------------------------> start create
            |                           |
            |                           |
            |                           |
            |                           | end create
            |                           | start function
            |      send                 | start map 
            +---------------------------> 
            |                           |
            |                           |
            |     ????    <- - - - - - -+
            |                           |
            |                           |
            |                           ~ end of map
            |                           |
            |                           |
            |                           |
            |                           |
            +                           +





To counter the effects of delay , let us insert a 1000 ms waiting on the MTC side:

testcase tc_SNMP_1()runs on Test_SNMP_CT
{

  var Echo_SNMP_CT v_echo_CT := Echo_SNMP_CT.create alive;  
  timer T := 5.0;
  
  v_echo_CT.start(f_echo())

  timer T0 := 1.0;
  T0.start;
  T0.timeout;
 
  map(self:UDP_PCO_DF, system:UDP_PCO_DF);
  var integer v_Id := f_Test_openConnection(tsp_connectionParams,-1); 
//SNMP V1
  UDP_PCO_DF.send(t_snmp_v1_getrequest_msg(5,{}));
 
  T.start;
  alt 
  {
    []UDP_PCO_DF.receive(t_snmp_v1_getrequest_msg(5,{}))
      {setverdict(pass);T.stop;} 
         
    []UDP_PCO_DF.receive
      {setverdict(fail);T.stop;v_echo_CT.stop;stop} 
       
    [] T.timeout {setverdict(fail);v_echo_CT.stop;stop}              
  }	
:
:



As it can be seen from the generated log , now the test case passes:



2017/May/31 08:31:44.429801 PORTEVENT SNMP_Test2.ttcn:212 Sent on UDP_PCO_DF to system @SNMPmsg-Types.SNMPv1-Message : { version := 0, community := '7075626C6963'O ("public"), data := { get_request := { request_id := 5, error_status := 1, error_index := 1, variable_bindings := { } } } }
2017/May/31 08:31:44.429922 PORTEVENT SNMP_Test2.ttcn:212 Outgoing message was mapped to @UDPasp_Types.ASP_UDP_message : { data := '301802010004067075626C6963A00B0201050201010201013000'O, remote_addr := "127.0.0.1", remote_port := 35000, id := 0 }
2017/May/31 08:31:44.429995 TIMEROP SNMP_Test2.ttcn:214 Start timer T: 5 s
2017/May/31 08:31:44.430399 PORTEVENT SNMP_Test2.ttcn:215 Message enqueued on UDP_PCO_DF from system @UDPasp_Types.ASP_UDP_message : { data := '301802010004067075626C6963A00B0201050201010201013000'O, remote_addr := "127.0.0.1", remote_port := 35000, id := 0 } id 2
2017/May/31 08:31:44.430557 PORTEVENT SNMP_Test2.ttcn:215 Incoming message was mapped to @SNMPmsg-Types.SNMPv1-Message : { version := 0, community := '7075626C6963'O ("public"), data := { get_request := { request_id := 5, error_status := 1, error_index := 1, variable_bindings := { } } } } id 2
2017/May/31 08:31:44.430605 MATCHING SNMP_Test2.ttcn:217 Matching on port UDP_PCO_DF succeeded:  matched
2017/May/31 08:31:44.430626 PORTEVENT SNMP_Test2.ttcn:217 Receive operation on port UDP_PCO_DF succeeded, message from system(): @SNMPmsg-Types.SNMPv1-Message : { version := 0, community := '7075626C6963'O ("public"), data := { get_request := { request_id := 5, error_status := 1, error_index := 1, variable_bindings := { } } } } id 2
2017/May/31 08:31:44.430643 PORTEVENT SNMP_Test2.ttcn:217 Message with id 2 was extracted from the queue of UDP_PCO_DF.
2017/May/31 08:31:44.430658 VERDICTOP SNMP_Test2.ttcn:218 setverdict(pass): none -> pass
2017/May/31 08:31:44.430696 TIMEROP SNMP_Test2.ttcn:218 Stop timer T: 5 s



It appears that we can relax now and have a beer; this is a dangerous self-deception I warn you against.
What happens is, when one is trying to synchronize based on timers and waiting periods it will build implied assumptions into the code;
such an assumption in our case is that "creating the PTC, starting the function on it and mapping the port should take less than n milliseconds",
which seems to be a reasonable assumption; but if circumstances change , the assumption may fail, causing difficult-to-detect faults.
These assumption will connect in chains of causality sooner or later rendering the system unstable.
A more rigorous synchronization mechanism, such as a message based one, is always to be preferred.
Timers best be used to detect situations when expected messages do not arrive, possibly due to some fault.


So let's add control (or synchronization, if you prefer ) ports to SNMP_Test2.ttcn:

type port Ctrl_PT message  
{  
inout charstring
}  with {extension "internal"}

type component Echo_SNMP_CT
{
  port  UDPasp_PT UDP_PCO;  // echo port
  port  Ctrl_PT Ctrl_PCO;  // control port
}

type component Test_SNMP_CT
{
  port  SNMP_UDP_PT UDP_PCO_DF; 
  port  Ctrl_PT Ctrl_PCO;
}

:
:

function f_echo() runs on Echo_SNMP_CT
{  
   var ASP_UDP         v_ASP_UDP_r, v_ASP_UDP 
  
   timer T1 := 0.1; 
   T1.start;T1.timeout;  
   map(self:UDP_PCO, system:UDP_PCO);
    
   Ctrl_PCO.send("Go"); //send synch 
  
   alt 
   {
:
:   


testcase tc_SNMP_1() runs on Test_SNMP_CT
{

  timer T := 5.0;


  var Echo_SNMP_CT v_echo_CT := Echo_SNMP_CT.create alive;  
  connect(self:Ctrl_PCO, v_echo_CT:Ctrl_PCO);
  
  v_echo_CT.start(f_echo())
 
  map(self:UDP_PCO_DF, system:UDP_PCO_DF);
  Ctrl_PCO.receive("Go") {};//receive synch
  
  var integer v_Id := f_Test_openConnection(tsp_connectionParams,-1);  

//SNMP V1
  UDP_PCO_DF.send(t_snmp_v1_getrequest_msg(5,{}));
 
  T.start;
  alt 
  {
    []UDP_PCO_DF.receive(t_snmp_v1_getrequest_msg(5,{}))
      {setverdict(pass);T.stop;} 
         
    []UDP_PCO_DF.receive
      {setverdict(fail);T.stop;v_echo_CT.stop;stop} 
       
    [] T.timeout {setverdict(fail);v_echo_CT.stop;stop}              
  }




The following snippet from the merged execution log demonstrates the synchronization mechanism:


:
:
 
2017/May/31 08:34:29.907235 3 PARALLEL - Initializing variables, timers and ports of component type SNMP_Test2.Echo_SNMP_CT inside testcase tc_SNMP_1.
2017/May/31 08:34:29.907329 3 PORTEVENT - Port UDP_PCO was started.
2017/May/31 08:34:29.907355 3 PORTEVENT - Port Ctrl_PCO was started.
2017/May/31 08:34:29.907364 3 PARALLEL - Component type SNMP_Test2.Echo_SNMP_CT was initialized.
2017/May/31 08:34:29.907394 mtc PARALLEL SNMP_Test2.ttcn:204 PTC was created. Component reference: 3, alive: yes, type: SNMP_Test2.Echo_SNMP_CT.
2017/May/31 08:34:29.907427 mtc PARALLEL SNMP_Test2.ttcn:205 Connecting ports mtc:Ctrl_PCO and 3:Ctrl_PCO.
2017/May/31 08:34:29.907595 mtc PORTEVENT SNMP_Test2.ttcn:205 Port Ctrl_PCO is waiting for connection from 3:Ctrl_PCO on UNIX pathname /tmp/ttcn3-portconn-8c60bf6b.
2017/May/31 08:34:29.907679 3 PORTEVENT - Port Ctrl_PCO has established the connection with mtc:Ctrl_PCO using transport type UNIX.
2017/May/31 08:34:29.907757 mtc PORTEVENT SNMP_Test2.ttcn:205 Port Ctrl_PCO has accepted the connection from 3:Ctrl_PCO.
2017/May/31 08:34:29.907786 mtc PARALLEL SNMP_Test2.ttcn:205 Connect operation on mtc:Ctrl_PCO and 3:Ctrl_PCO finished.
2017/May/31 08:34:29.907817 mtc PARALLEL SNMP_Test2.ttcn:210 Starting function f_echo() on component 3.
2017/May/31 08:34:29.907903 3 PARALLEL - Starting function f_echo().
2017/May/31 08:34:29.907926 3 TIMEROP SNMP_Test2.ttcn:95 Start timer T1: 1 s
2017/May/31 08:34:29.908006 mtc PARALLEL SNMP_Test2.ttcn:210 Function was started.
2017/May/31 08:34:29.908028 mtc PARALLEL SNMP_Test2.ttcn:215 Mapping port mtc:UDP_PCO_DF to system:UDP_PCO_DF.
2017/May/31 08:34:29.908082 mtc PORTEVENT SNMP_Test2.ttcn:215 Port UDP_PCO_DF was mapped to system:UDP_PCO_DF.
2017/May/31 08:34:29.908134 mtc PARALLEL SNMP_Test2.ttcn:215 Map operation of mtc:UDP_PCO_DF to system:UDP_PCO_DF finished.
2017/May/31 08:34:30.909217 3 TIMEROP SNMP_Test2.ttcn:95 Timeout T1: 1 s
2017/May/31 08:34:30.909282 3 PARALLEL SNMP_Test2.ttcn:96 Mapping port 3:UDP_PCO to system:UDP_PCO.
2017/May/31 08:34:30.909521 3 WARNING SNMP_Test2.ttcn:96 Warning: The maximum number of open file descriptors (8193) is greater than FD_SETSIZE (1024). Ensure that Test Ports using Install_Handler do not try to wait for events of file descriptors with values greater than FD_SETSIZE (1024). (Current caller of Install_Handler is "UDP_PCO")
2017/May/31 08:34:30.909580 3 PORTEVENT SNMP_Test2.ttcn:96 Port UDP_PCO was mapped to system:UDP_PCO.
2017/May/31 08:34:30.909669 3 PARALLEL SNMP_Test2.ttcn:96 Map operation of 3:UDP_PCO to system:UDP_PCO finished.
2017/May/31 08:34:30.909707 3 PORTEVENT SNMP_Test2.ttcn:98 Sent on Ctrl_PCO to mtc charstring : "Go"
2017/May/31 08:34:30.909793 mtc PORTEVENT SNMP_Test2.ttcn:223 Message enqueued on Ctrl_PCO from 3 charstring : "Go" id 1
2017/May/31 08:34:30.909848 mtc MATCHING SNMP_Test2.ttcn:223 Matching on port Ctrl_PCO succeeded: "Go" with "Go" matched
2017/May/31 08:34:30.909881 mtc PORTEVENT SNMP_Test2.ttcn:223 Receive operation on port Ctrl_PCO succeeded, message from 3: charstring : "Go" id 1
2017/May/31 08:34:30.909899 mtc PORTEVENT SNMP_Test2.ttcn:223 Message with id 1 was extracted from the queue of Ctrl_PCO.
2017/May/31 08:34:30.909932 mtc PORTEVENT SNMP_Test2.ttcn:67 Sent on UDP_PCO_DF to system @UDPasp_Types.ASP_UDP_open : { remote_addr := "127.0.0.1", remote_port := 35000, local_addr := "127.0.0.1", local_port := 0 }
  :
  :
  


In summary:


-lack of global variables is not an omission , it's deliberate
-loose , timer-based synchronization should be avoided, as it may inject hard-to-debug faults
-strict, message-coupled synchronization is to be preferred , although it has a bit of an overhead

Finally, this s how the above described architecture will look like. Note the synchronization (or control ) ports
connecting the MTC to PTCs.




			sync
       +----------------------------------------------------------+
       |       sync                                               |
       |   +--------------------+                                 |
       |   |                    |                                 |
+------+---+---+       +--------v-----+                 +---------v----+
|              |       |              |                 |              |
|              |       |              |                 |              |
|              |       |              |                 |              |
|    MTC       |       |   PTC1       |      ...        |   PTCn       |
|              |       |              |                 |              |
|              |       |              |                 |              |
+--------------+       +---------+----+                 +-------+------+
                                 |                              |
                                 |                              |
                                 |                              |
                                 |                              |
                                 |                              |
                          +------v------------------------------v------+


                                             SUT

									




Best regards
Elemer

[Updated on: Thu, 01 June 2017 06:52]

Report message to a moderator

Previous Topic:Translation ports vs dual-faced ports part3
Next Topic:Collecting test suite from executable
Goto Forum:
  


Current Time: Fri Mar 29 11:49:52 GMT 2024

Powered by FUDForum. Page generated in 0.01576 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top