Studio:How to synchronize scripts: Difference between revisions

From STRIDE Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
If a test scenario requires multiple scripts synchronization between the scripts is required. For example if testing a component requires to simulate a depend component it is sometimes easier to split it in multiple scripts. One script could be driving the test which launches a separate script non-blocking which simulates the depended component.  
If a test scenario requires multiple scripts, synchronization between the scripts is required. For example, if testing a component requires you to simulate a dependent component it is sometimes easier to split the task into multiple scripts. One script drives the test, which launches a separate script non-blocking which simulates the dependent component.  


The following example shows how communication between two scripts can be achieved using a simple client-server example. The client queries the server for date and time. The server returns a date and time string.
The following example shows how communication between two scripts can be achieved using a simple client-server example. The client queries the server for date and time. The server returns a date and time string.


The interface between the client and server is defined in a SCL file. For the example the SCL files has two interfaces, one to request information (in the example the date and time string) and one to shutdown (end) the server script.  
The interface between the client and server is defined in a SCL file. In this example the SCL file has two interfaces, one to request information (in the example the date and time string) and a "dummy" function that exists solely to allow us to notify the server script that it should end.


SCL File:
; Note: An alternative to this synchronization technique is shown in the article [[Using Scripts to Simulate Missing Software Units]].
#define MAX_STRING_SIZE 50
int get_time(char* szTime);
int shutdown(void);
#ifdef _SCL
#pragma scl_function(get_time)
#pragma scl_ptr(get_time.szTime,  OUT,  PRIVATE)
#pragma scl_string(get_time.szTime, MAX_STRING_SIZE)
#pragma scl_function(shutdown)
#endif /* _SCL */ 


The server scripts waits for requests, gets the time and returns requests:
==SCL File==
  ## Used interfaces
<source lang="c">
  my $req      = $main::ascript->Functions->Item("get_time")->Owner;
#define MAX_STRING_SIZE 50
  my $shutdown = $main::ascript->Functions->Item("shutdown")->Owner;
int get_time(char* szTime);
 
#ifdef _SCL
/* this is the dummy function declaration, used for communication
  between the client and server scripts */
void shutdown(void);
#pragma scl_function(get_time)
#pragma scl_ptr(get_time.szTime,  OUT,  PRIVATE)
#pragma scl_string(get_time.szTime, MAX_STRING_SIZE)
#pragma scl_function(shutdown)
#endif /* _SCL */ 
</source>
 
==Server Script==
The server script waits for requests, gets the time and returns requests:
<source lang="perl">
## Used interfaces
my $req      = $main::ascript->Functions->Item("get_time")->Owner;
my $shutdown = $main::ascript->Functions->Item("shutdown")->Owner;
    
    
  ## teake ownership of required interfaces
## take ownership of required interfaces
  $req->Register();
$req->Register();
  $shutdown->Register();
$shutdown->Register();
    
    
  ## initialize exit variable
## initialize exit variable
  my $end = 0;
my $end = 0;
    
    
  ## Wait for requests from clients until exit
## Wait for requests from clients until exit
  while ($end == 0)
while ($end == 0)
  {
{
    ## Wait for an event
  ## Wait for an event
    my $event = $main::ascript->WaitForEvent();
  my $event = $main::ascript->WaitForEvent();
    
    
    ## if the event is a get time request, get the time
  ## if the event is a get time request, get the time
    ## and return
  ## and return
    if ($event->Name eq $req->Name)
  if ($event->Name eq $req->Name)
    {
  {
        $req->OutPointers->{szTime} = gmctime();
      $req->OutPointers->{szTime} = gmctime();
        $req->{ReturnValue} = 1;
      $req->{ReturnValue} = 1;
        $req->Return();
      $req->Return();
    }
  }
    
    
    ## Shutdown event. Set the variable to exit the loop
  ## Shutdown event. Set the variable to exit the loop
    if ($event->Name eq $shutdown->Name)
  if ($event->Name eq $shutdown->Name)
    {
  {
        $shutdown->{ReturnValue} = 1;
      $shutdown->{ReturnValue} = 1;
        $shutdown->Return();
      $shutdown->Return();
        $end = 1;
      $end = 1;
    }
  }
  }
}
    
    
  ## Unregister ownership
## Unregister ownership
  $req->Unregister();
$req->Unregister();
  $shutdown->Unregister();
$shutdown->Unregister();
 
</source>


==Client Script==
The client script queries the server. However it also assures that the server is running. To show how scripts can be launched and terminated the client scripts first checks if the server is running. If not it starts the server and waits until the server is ready to accept requests. This is done by waiting until the server has registered the interfaces for script communication. At the end the client script sends a shutdown request to the server to end the server script.
The client script queries the server. However it also assures that the server is running. To show how scripts can be launched and terminated the client scripts first checks if the server is running. If not it starts the server and waits until the server is ready to accept requests. This is done by waiting until the server has registered the interfaces for script communication. At the end the client script sends a shutdown request to the server to end the server script.
 
<source lang="perl">
  ## Check if server is running
## Check if server is running
   if (!($main::ascript->Functions->Item("shutdown")->Owner->IsRegistered))
if (!($main::ascript->Functions->Item("shutdown")->Owner->IsRegistered))
{
  ## Server not available
  ## As an option we can start the server here
   ## This might not be required in all cases but is a good sample
  ## on how to start another script non-blocking
  $main::studio->Workspace->Files->Item("server.pl")->RunNonBlocking();
 
  ## wait for the server to be up
  ## An easy way is to wait until the server has taken ownership
  ## of the supported functions
  while (!($main::ascript->Functions->Item("shutdown")->Owner->IsRegistered))
   {
   {
    ## Server not available
      $main::ascript->Sleep(100);
    ## As an option we can start the server here
    ## This might not be required in all cases but is a good sample
    ## on how to start another script non-blocking
    $main::studio->Workspace->Files->Item("server.pl")->RunNonBlocking();
 
    ## wait for the server to be up
    ## An easy way is to wait until the server has taken ownership
    ## of the supported functions
    while (!($main::ascript->Functions->Item("shutdown")->Owner->IsRegistered))
    {
        $main::ascript->Sleep(100);
    }
 
   }
   }
}
    
    
  ## Get a shortcut to the function
## Get a shortcut to the function
  my $req = $main::ascript->Functions->Item("get_time")->User;
my $req = $main::ascript->Functions->Item("get_time")->User;
    
    
  ## Call te function (blocking request to the server)
## Call the function (blocking request to the server)
  $req->Call();
$req->Call();
    
    
  ## Check for the return value and display date and time
## Check for the return value and display date and time
  if ($req->ReturnValue)
if ($req->ReturnValue)
  {
{
      $main::ascript->MessageBox($req->OutPointers->szTime, "Current Time");
    $main::ascript->MessageBox($req->OutPointers->szTime, "Current Time");
  }
}
  else
else
  {
{
    $main::ascript->MessageBox("Server returned Error", "Error");
  $main::ascript->MessageBox("Server returned Error", "Error");
  }
}
    
    
  ## Shutdown the server (if required)
## Shutdown the server (if required)
  $main::ascript->Functions->Item("shutdown")->User->Call();</nowiki>
$main::ascript->Functions->Item("shutdown")->User->Call();
 
</source>






[[Category:Scripting]]
[[Category:Scripting]]

Revision as of 16:10, 11 March 2008

If a test scenario requires multiple scripts, synchronization between the scripts is required. For example, if testing a component requires you to simulate a dependent component it is sometimes easier to split the task into multiple scripts. One script drives the test, which launches a separate script non-blocking which simulates the dependent component.

The following example shows how communication between two scripts can be achieved using a simple client-server example. The client queries the server for date and time. The server returns a date and time string.

The interface between the client and server is defined in a SCL file. In this example the SCL file has two interfaces, one to request information (in the example the date and time string) and a "dummy" function that exists solely to allow us to notify the server script that it should end.

Note
An alternative to this synchronization technique is shown in the article Using Scripts to Simulate Missing Software Units.

SCL File

#define MAX_STRING_SIZE 50
int get_time(char* szTime);

#ifdef _SCL
/* this is the dummy function declaration, used for communication 
   between the client and server scripts */
void shutdown(void);
#pragma scl_function(get_time)
#pragma scl_ptr(get_time.szTime,  OUT,  PRIVATE)
#pragma scl_string(get_time.szTime, MAX_STRING_SIZE)
#pragma scl_function(shutdown)
#endif /* _SCL */

Server Script

The server script waits for requests, gets the time and returns requests:

## Used interfaces
my $req      = $main::ascript->Functions->Item("get_time")->Owner;
my $shutdown = $main::ascript->Functions->Item("shutdown")->Owner;
  
## take ownership of required interfaces
$req->Register();
$shutdown->Register();
  
## initialize exit variable
my $end = 0;
  
## Wait for requests from clients until exit
while ($end == 0)
{
   ## Wait for an event
   my $event = $main::ascript->WaitForEvent();
  
   ## if the event is a get time request, get the time
   ## and return
   if ($event->Name eq $req->Name)
   {
      $req->OutPointers->{szTime} = gmctime();
      $req->{ReturnValue} = 1;
      $req->Return();
   }
  
   ## Shutdown event. Set the variable to exit the loop
   if ($event->Name eq $shutdown->Name)
   {
      $shutdown->{ReturnValue} = 1;
      $shutdown->Return();
      $end = 1;
   }
}
  
## Unregister ownership
$req->Unregister();
$shutdown->Unregister();

Client Script

The client script queries the server. However it also assures that the server is running. To show how scripts can be launched and terminated the client scripts first checks if the server is running. If not it starts the server and waits until the server is ready to accept requests. This is done by waiting until the server has registered the interfaces for script communication. At the end the client script sends a shutdown request to the server to end the server script.

## Check if server is running
if (!($main::ascript->Functions->Item("shutdown")->Owner->IsRegistered))
{
  ## Server not available
  ## As an option we can start the server here
  ## This might not be required in all cases but is a good sample
  ## on how to start another script non-blocking
  $main::studio->Workspace->Files->Item("server.pl")->RunNonBlocking();
  
  ## wait for the server to be up
  ## An easy way is to wait until the server has taken ownership
  ## of the supported functions
  while (!($main::ascript->Functions->Item("shutdown")->Owner->IsRegistered))
  {
       $main::ascript->Sleep(100);
  }
}
  
## Get a shortcut to the function
my $req = $main::ascript->Functions->Item("get_time")->User;
  
## Call the function (blocking request to the server)
$req->Call();
  
## Check for the return value and display date and time
if ($req->ReturnValue)
{
    $main::ascript->MessageBox($req->OutPointers->szTime, "Current Time");
}
else
{
  $main::ascript->MessageBox("Server returned Error", "Error");
}
  
## Shutdown the server (if required)
$main::ascript->Functions->Item("shutdown")->User->Call();