Studio:How to synchronize scripts

From STRIDE Wiki
Revision as of 16:10, 11 March 2008 by Timd (talk | contribs)
Jump to navigation Jump to search

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();