QASH Syntax 2.7.x

This file describes the allowed syntax for the QASH syntax as used by the QASHParser class.

Quick links:
AUTOCLEAN_ON AUTOCLEAN_OFF,






CALLFUNCTION CHECKAGENT CMDCLEAN CHECKFILE CHECKFILE_LOCAL CMDGETTRACE CMDSTART CMDSTATUS CMDSTOP
DELAGENT DELFILE DELFILE_LOCAL DELPROP DELSTATIC DAEMONSTART


ENVTRACECONTAINS







FUNCTION







GETFILE GETSTATIC GETTRACEPATHS





KILLAGENT







MKDIR MKDIR_LOCAL






PRINT PRINTENV






RANDOM REPORTSTATUS






SENDFILE SETPROP SETAGENT SETSTATIC SLEEP STDERRCONTAINS STDOUTCONTAINS

ZIPSEND ZIPCLEAN ZIPCREATE_LOCAL






 

STRING_CONSTANT

Denoted by quotes
e.g.

"This is a string constant"
String constants may not extend across multiple lines.
 
 

OPERATORS

The following boolean operators are allowed :
 
>
Greater than
<
Less than
>=
Greater than or equal to
>=
Less than or equal to
==
Equal to
!=
Not equal to

They may be applied to Strings or to numerical constants. If either the left side or the right side of an expression is found to be non numerical,
both sides are treated as String values.

The following assignment operators are allowed :
 
= Simple assignment operator, assigning the value on the right side to the key specified on the left.
If the current file is a properties file, standard java properties conventions are used.
e.g. :
Test=Test string
If the currently parsed file is not a properties file, all non quoted portions of the right side are expected to be 
variables.
e.g.:
Test1 = "Test string"
Test2 = "Another Test string"+Test1
+= If both sides of the operator are numerical values, the result is a numerical addition of the two values, 
otherwise it is treated as a String concatenation
? This is a soft set operator. The assignment is only applied if the Left side is not yet defined.
e.g.:
Test = "Test string"
Test ? "New test string"
Test2 ? "New test string"
The variable Test will still contain the value "Test string" and variable
Test2 will contain "New test string"

 

VARIABLE DEFINITION

A variable is defined by a statement of the form
VAR_NAME <assignment operator> VALUE

Lets look at a code segment :

# create and sets a variable called INDEX to zero
INDEX = 0
# increment the value of INDEX by 5.
INDEX += 5
# append the string "abc" to index, so it will now contain "5abc"
INDEX = INDEX + "abc"


Note: variables are global, so nested changes to loop variables will be visible everywhere in the instance of the QASHParser object.

Complex references of variables are allowed, so after the above definitions we could say :

TEMP1 = "Test String"
TEMP2 = TEMP+"1"
TEMP3 = (TEMP+"1")+"2"
The variable TEMP2 will now contain the value "Test String" and TEMP3 will contain "Test String 2"
The shell parser first checks if the variable TEMP is defined, if not it checks for
a variable called TEMP1, which IS defined, and uses this value to initialize TEMP2.
 

IF Statements

These are of the form

IF (agent1.os.name == "Windows NT")
        THEN
                FILE_SEPARATOR="\"
                KEYWORDS = "windows"
                TMP_DIR = "c:\tmp"
        ELSE
                FILE_SEPARATOR="/"
                KEYWORDS = "solaris"
                TMP_DIR = "/tmp"
END
Each statement of the matching THEN and ELSE statements may contain further nested IF statements.
The boolean expression may use any of the boolean operators listed in the section OPERATORS but no assignment may be made in this statement.
The ELSE statement is optional, and may be left out.
 
 

FOR Statements

For statements can be used to save repeating code blocks within your .qash files.
Here are some examples :

Example 1:

FOR I = 0 TO 10 BY 2 DO
    PRINT I
END

Will print out the numbers 0, 2, 4, 6, 8, 10


Example 2:

FOR I = 1 TO 4 DO
    FOR J = 1 TO 4 DO
        PRINT "I is "+I+" and J is "+J
    END
END

Will print out  :

I is 1 and J is 1
I is 1 and J is 2
...
I is 1 and J is 3
I is 4 and J is 4

 
 

WHILE

The WHILE statement allows us to execute a particular code block until a certain expression evaluates to TRUE.

e.g.

I = 0;
WHILE (I < 10) DO
    PRINT I
    I += 1
END
Which will print out the numbers 0 through to 9.
The statement portion of a WHILE loop may contain nested WHILE loops.
 

We now come to the set of commands available to the .qash script files.
They will be discussed in order of usage, rather than alphabetically, to simplify the explanations.
 

Mandatory variable definitions

Several properties are mandatory for each .qash file, TEST_NAME and KEYWORDS.
TEST_NAME is the string you will see beside the node entry in the test tree of the Harness.
The KEYWORDS property is a list of keywords used for test selection.
e.g.:

qat.test.name = "Robustness Test"
qat.test.keywords = "robustness windows solaris"
qat.test.description = "This is a robustness test for Windows and Solaris"
qat.test.author = "webhiker"
qat.test.buginfo = ""

Available System variables

The are a number of variables available to the .qash scripts
The x indicates this variable exists for each agent defined for a particular project, so X will vary from 1 to qat.agent.count.
 
qat.agent.count The number of agents defined for this project.
Useful for use in FOR loops defining properties for each agent, as well as the total number of agents which have been defined.
agentx_name The name of the machine running the agent
agentx_port The port number of the agent running on the machine AGENTx_NAME
agentx_os.name This is the operating system reported by the Java Virtual machine running the agent on machine AGENTx_NAME.
Care should be taken since different JVM implementations report different values for the same OS. e.g. Solaris/SunOS etc.
It is retrieved by checking the value of java.lang.System os.name
agentx_os.architecture This is the underlying architecture type of the machine running the agent.
Care should be taken since different JVM implementations report different values for the same architecture. e.g. x86/Intel etc.
It is retrieved by checking the value of java.lang.System os.arch
qat.project.path This is the root path to the directory containing the tests displayed in the test tree
qat.qash.filepath The path to the file currently being parsed, including the name of the file itself
qat.qash.path The path to the file currently being parsed, excluding the name of the file itself

 
 

INCLUDE <INCLUDEFILE>

The include keyword is used to include a properties file (*.properties) of the format specified by java.util.Properties, or a file containing QASH syntax designated by it's extension (*.qinc or*.qash).
By default, all files are treated as QASH syntax unless they specifically have a .properties extension.
It should be noted however, that parsing a Properties file is many orders of magnitude faster than parsing a QASH syntax file, and so should be used wherever possible.

e.g. :

QAT_ROOT="/home/webhiker/QAT"
INCLUDE QAT_ROOT+"/examples/settings/agent_setup.qinc"
A good hint is to try and avoid using explicit paths as in the example above, since this limits your Harness to running on a single architecture.
Have a look at the examples to see how to define .qash scripts which run across a variety of platforms.
 
 

SETAGENT(AGENT_ID, AGENT_NAME, AGENT_PORT, WORK_DIR)

This command sets up an agent for use by a .qash file,  gets a handle to a running agent, and sets the value of this handle in AGENT_ID.

AGENT_NAME - the name of the machine running the agent (use one of the AGENTx_NAME variables here)
AGENT_PORT - the port number of the agent running on machine (use one of the AGENTx_PORT variable here)
WORK_DIR - a directory to place any files sent to this agent via the ZIPSEND command. This paramter is a file path relative to the agent.
If the variable AGENT_ID exists prior to this call, an exception is generated.
Each call to the SETAGENT command should be matched by a call to DELAGENT when the .qash file has finished using the agent.
If the directory specified by WORK_DIRdoes not exist prior to the call to SETAGENT, then it will be automatically created. When the corresponding DELAGENT command is called, the entire directory and it's contents will be deleted if the AUTOCLEAN_ON command was called.
 
 

SETSTATIC(KEY,VALUE)

This command will set a static variable which will be visible to all QASH scripts for the lifetime of the JVM, or until it is explicitly deleted by a call to DELSTATIC. It allows rudimentary exchange of information between tests.

KEY- the name of the variable to be used for use in later calls to GETSTATIC
VALUE- the value to place in this variable

e.g. :

SETSTATIC(MYVAR,"300")
GETSTATIC(RESULT,MYVAR)
The variable RESULT will then contain the value "300". Furthermore, the call to GETSTATIC may be made at any time during the lifetime of the JVM and it will still contain this value.

 

DELSTATIC(KEY,VALUE)

This command will delete a static variable set in a prior call to SETSTATIC. If the variable does not exist, it will not complain.

KEY- the name of the static variable to remove
VALUE- the value to place in this variable

 

GETSTATIC(RESULT,KEY)

This command will get a static variable which must have been set by a prior call to DELSTATIC. If the variable does not exist, KEY will not be set.

RESULT- the result will be stored in a variable of this name
KEY- the name of the static variable to be retrieved


 

ZIPSEND(AGENT_ID, ZIP_ID, ZIP_FILENAME)

This command sends a zip file to the agent specified in AGENT_ID (created by a call to SETAGENT) and unzips the file in the selected WORK_DIR for this AGENT_ID.

AGENT_ID - which agent to send the zip file to, created by a previous call to SETAGENT
ZIP_ID - the handle to the zip file will be created in this variable, so it must be undefined at this point. It will be used later when the call is made to ZIPDEL
ZIP_FILENAME - the full path to the zip file you want to send (relative to the harness)
This command will transfer to requested file to the relative agent, and the agent will then unzip this file in the WORK_DIRECTORY you specified in the call to SETAGENT
 
 

SETPROP(AGENT_ID, KEY, VALUE) or SETPROP(AGENT_ID,KEY)

This command sets a property value on the specified AGENT_ID, which will be visible to any subsequent CMDSTART commands called on this AGENT_ID.
Note: If form two of this command is used, no resolving of the parameters will be done, they will be set on the agent exactly as they appear here. Leading and trailing spaces in the parameters are ignored.

AGENT_ID - the agent on which the property must be set
KEY - the key name of the property
VALUE - the value of the property. If omitted, it will be retrieved from the .qash environment. If it is not defined here either, it will be assigned to the same value as KEY.
e.g..
Form 1:
KEY="VALUE"
SETPROP(AgentID,KEY);
will result in an environment variable pair "KEY=VALUE" being visible to any process executing on the agent specified by AgentID.
SETPROP(AgentID,KEY,"VALUE");

Form 2:
KEY="VALUE"
SETPROP(AgentID,KEY,"VALUE");
will result in an environment variable pair "VALUE=VALUE" being visible to any process executing on the agent specified by AgentID.
 

SETPROP(myAgent, "SystemRoot","c:\winnt")
    will set the value "SystemRoot=c:\winnt"


 

DELPROP(AGENT_ID, KEY, VALUE) or DELPROP(AGENT_ID, KEY)

This command removes a property from the agent AGENT_ID, so it will no longer be visible to any subsequent calls to CMDSTART.
It does not matter if the property KEY existed previously or not.

AGENT_ID - the agent on which the property must be deleted
KEY - the key name of the property to be deleted
VALUE - the value of the property to be deleted. Not neccesary to use this form.

CMDSTART(AGENT_ID, CMD_ID, CMD_STRING, TIMEOUT) or CMDSTART(AGENT_ID, CMD_ID, CMD_STRING)

This spawns an execute process on the agent, using an environment built from any calls to SETPROP, and then executing the command specified in CMD_STRING.

AGENT_ID- the agent on which the command is to be executed
CMD_ID - a handle to be used for further communication of this started process
CMD_STRING - the command to be executed on the agent (must be relative to the agent's OS and architecture)
TIME_OUT - after this value, specified in seconds, the process will be killed if it does not exit normally. Warning :If this value is omitted, and a call is made to CMDSTATUS, the agent will block until the process exits!

 

CMDSTOP(CMD_ID) or CMDSTOP(CMD_ID ,STATUS_CODE)

This command stops a previously started process if it is still running. If it had previously exited normally, this method has no effect.

CMD_ID - the handle of the process whom we are trying to stop.
STATUS_CODE - the return value of the process if it already finished, or a negative value if had to be killed.
Warning: A common programming error is to do the following :
CMDSTART(agent_id, cmd_id, cmd_string, cmd_timeout)
CMDSTOP(cmd_id)
Due to the speed of the parser executing these statements, the STOP command usually kills the process before it has had a chance to start, so it would be better to use the following code :
CMDSTART(agent_id, cmd_id, cmd_string, cmd_timeout)
SLEEP(10)
CMDSTOP(cmd_id)

 
 

CMDSTATUS(CMD_ID, STATUS_CODE)

This command tries to receive the exit value of the process started by the CMDSTART command.
A call to this command will block until such time as the process exits, or times out, so it is suggested that every call to CMDSTART use a reasonable TIMEOUT value, or makes a call to CMDSTOP prior to the call to CMDSTATUS.

CMD_ID - the handle of the process who's value we are interested in
STATUS_CODE - the process exit value will be placed in this variable. It may not exist prior to this call. A value of 0 indicates success, any other value indicates the process exited abnormally.

 

CMDCLEAN(CMD_ID)

This command cleans any temporary files associated with a process started by the CMDSTART command.
Failure to correctly clean a command may result in a parser warning being printed, indicating cleaning was not completely realised.

CMD_ID - the handle of the process who's files we want to clean.

 

CMDGETTRACE(CMD_ID)

This is used to retrieve the standard output and standard error streams produced by the process started in a previous call to CMDSTART.
It should typically be called only after a process has exited, i.e. make a call to CMDSTATUS before trying to get it's trace files.
These files are stored on the Harness project settings, and may be viewed by right clicking on a test node in the test tree of the GUI.
You do not have to call this method, so you need only use it for processes who's output is of interest. These files are all deleted by a call to DELAGENT, and will not be retrievable afterwards.

CMD_ID - the command identifier of the process who's trace you wish to retrieve.

DAEMONSTART(AGENT_ID, CMD_STRING) 

This spawns an execute process on the agent, using an environment built from any calls to SETPROP, and then executing the command specified in CMD_STRING. The command is expected to be a daemon process, and because of this, there is no way to either stop the process or retrieve any of it's output traces. This is in line with standard daemon behaviour.

AGENT_ID- the agent on which the daemon is to be executed
CMD_STRING - the daemon to be executed on the agent (must be relative to the agent's OS and architecture)

 

ZIPCLEAN(ZIP_ID)

This command cleans up all files previously created by a call to ZIPSEND, as well as the zip file itself.

 
ZIP_ID - the handle of the zipfile returned by the ZIPSEND command

ZIPCREATE_LOCAL(ZIPFILENAME,DIRNAME)

This command creates a new Zip file at the localtion ZIPFILENAME, and adds the contents of the directory specified by DIRNAME. This can then be used in subsequent ZIPSEND and ZIPCLEAN commands. It should nornally be cleaned up by the user, using an approproate DELFILE_LOCAL(..) command.

 

DELAGENT(AGENT_ID)

This function frees resources associated with AGENT_ID, and releases the AGENT_ID variable.
Any started processes not explicitly killed will be killed by this call, and their respective trace files will be deleted.
If the AGENT_ID is not defined, or does not match any previous calls to SETAGENT, an exception is thrown.

AGENT_ID- the agent whom we want to cleanup

 

KILLAGENT(RESULT, AGENT_NAME, AGENT_PORT)

This command instructs the agent to commit suicide. If the requests suceeds, RESULT will contain 0, if it fails, RESULT will be non-zero.

AGENT_NAME - the name of the machine running the agent.
AGENT_PORT - the port number of the agent running on machine.
RESULT - the status of the request (0 = succeeded, 1 = failed)

REPORTSTATUS(STATUS_CODE)

This is the final value which will be reported to the test harness, to decide whether a test passed or failed.
A value of 0 indicates a test passed, any other value indicates a failure.
In this way, the results of multiple processes on multiple agents can be combined by the .qash file, and then a test result
can be decided upon.
Note: Any parsing problems encountered will always cause a test to have an UNRESOLVED status, over-riding any actual passes or failures.

STATUS_CODE- any integer value, with 0 signifying a test passed, any other value indicates test failure.

 

SLEEP(SECONDS)

This function causes the parser execution to pause for the specified number of seconds. All processes started on the agents are unaffected.

SECONDS - the number of seconds to sleep for

 

PRINT PRINT_STATEMENT

This function prints information to the standard out console of the QAT harness, if there is one. Starting a JVM via the -jar command on Microsoft Windows generally starts the Harness with a hidden console, and so it will not be visible.

PRINT_STATEMENT - the statement to be printed
Complex print statements are allowed :
e.g.
PRINT "The value of i="+i
PRINT "Agent name :"+AGENT+" Agent port:"+PORT

AUTOCLEAN_ON

This enables the parser action of automatically cleaning any uncleaned agents and commands upon calling the REPORTSTATUS command. It is disabled by default.
No parameters are required. If set to true, the contents of the directory as well as the directory itself, specified in the SETAGENT command, will be deleted if SETAGENT was responsible for creating this directory.
 

AUTOCLEAN_OFF

This disables the parser action of automatically cleaning any uncleaned agents and commands upon calling the REPORTSTATUS command. It is disabled by default.
No parameters are required.
 
 

PRINTENV

This function is for debugging purposes, and will print out all the current defined properties at this point in the parsing process.
No parameters are required.
 
 

GETFILE(AGENT_ID, SRC_PATH, DEST_PATH)

This function retrieves an arbitrary file from the agent.

AGENT_ID - the agent we want to retrieve the file from
SRC_PATH - the path to the file to be retrieved, relative to the agent
DEST_PATH - where to place the file once it is retrieved, relative to the harness
Bear in mind that the agent may be running on various platforms, so it is advised to use platform independent methods for specifying paths. For paths relative to the harness, you may make use of the standard java properties variables, such as file.separator.
 
 

SENDFILE(AGENT_ID, SRC_PATH, DEST_PATH)

This function sends an arbitrary file to the agent.

AGENT_ID - the agent we want to send the file to.
SRC_FILE - the path to the file to be sent, relative to the harness
DEST_FILE- full path to place the sent file relative to the agent

 

CHECKFILE(AGENT_ID, RESULT, FILENAME)

This function checks for the existence of an arbitrary file on the agent.

AGENT_ID - the agent on whom we we want to check the file.
RESULT - the result of the operation : 0 indicates the file exists, 1 indicates the file does exist.
FILENAME- the full path to the file to be checked,  relative to the agent

 

CHECKFILE_LOCAL(RESULT, FILENAME)

This function checks for the existence of an arbitrary file on the harness machine.

RESULT - the result of the operation : 0 indicates the file exists, 1 indicates the file does exist.
FILENAME- the full path to the file to be checked,  relative to the agent

 

MKDIR(AGENT_ID, FILENAME)

This function creates an arbitrary directory on the agent.

AGENT_ID - the agent on whom we we want to create the directory.
FILENAME- the full path to the file to be checked,  relative to the agent

 

MKDIR_LOCAL(FILENAME)

This function creates an arbitrary directory on the harness machine.

FILENAME- the full path to the file to be checked,  relative to the agent

 

CHECKAGENT(RESULT,  AGENT_NAME, AGENT_PORT)

This function checks for the existence of an arbitrary agent. If the agent exists,  all it's standard environment properties will then be available in the script with the prefix of the agent name.
e.g..  If AGENT1_NAME="machine1" then we will have machine1.os.name="Solaris".
Some of the variables are listed here :
      os.name - Operating system name
      os.arch - Operating system architecture
      os.version  - Operating system version
      file.separator  - File separator ("/" on UNIX)
      path.separator - Path separator (":" on UNIX)
      line.separator - Line separator ("\n" on UNIX)
      user.name - User's account name
      user.home - User's home directory
      user.dir - User's current working directory

RESULT - the result of the operation - zero indicates the agent was found, non-zero indicates agent not contactable.
AGENT_NAME - the name of the machine running the agent
AGENT_PORT - the port number the agent is registered to.

 

DELFILE_LOCAL(FILE_PATH)

This function will delete an arbitrary file from the harness machine. If the parameter is a directory, it and all it's sub directories will also be deleted so BE CAREFUL!

FILE_PATH - the path to the file/directory to be deleted, relative to the harness

DELFILE(AGENT_ID, FILE_PATH)

This function will delete an arbitrary file/directory from the agent machine. If the parameter is a directory, it and all it's sub directories will also be deleted so BE CAREFUL! If the file/directory specified by FILE_PATH does not exist, a parser error will be generated.

AGENT_ID - the agent where the file to be deleted resides
FILE_PATH - the path to the file to be deleted, relative to this agent

 

RANDOM(RID)

This function will generate a positive random integer value and place it into the variable specified by RID.
RID does not need to exists prior to this call, but if it does, it will be overwritten. RID may not be a complex expression.
 

RANDOM(toto)
PRINT toto

may set the value toto to 54324554

FUNCTION(FUNCTION_NAME,ARG1,...)

This allows you to define reusable blocks of code into callable functions. All statements up until the ENDFUNCTION keyword will be executed each time a matching call is made to CALLFUNCTION.
The function definition will be valid for the lifetime of the root node being parsed. Variable visibility is the same as that for INCLUDE statements.
A function must be defined with at least one argument. These arguments can be considered as "var" arguments, ie their value may be altered by the call to the function.

FUNCTION_NAME - the name for this function which we will later use to reference it.
ARG1 - one or more arguments to be passed when calling the function

eg:

FUNCTION(PRINT, STRING)
PRINT STRING
ENDFUNCTION

...

CALLFUNCTION(PRINT,"Hello World");

will generate the output :
Hello World

CALLFUNCTION(FUNCTION_NAME, ARG1,...)

This allows you to call a previously defined function. See FUNCTION(...) for details.
 

ENVTRACECONTAINS(COMMAND_ID, RESULT, STRING)

This function checks for the existence of string in the trace file output by the process COMMAND_ID. The check is done by a case-sensitive comparison.
This command must be preceded by a call to CMDGETTRACE(..), since the check is done on the QAT side, not an the agent side, so the file first needs to be retrieved from the agent.

COMMAND_ID - the command whose trace file we want to check.
RESULT - the result of the operation : 0 indicates the string exists, 1 indicates the string does exist.
STRING- the string to look for.

STDOUTCONTAINS(COMMAND_ID, RESULT, STRING)

This function checks for the existence of string in the trace file output by the process COMMAND_ID. The check is done by a case-sensitive comparison.
This command must be preceded by a call to CMDGETTRACE(..), since the check is done on the QAT side, not an the agent side, so the file first needs to be retrieved from the agent.

COMMAND_ID - the command whose trace file we want to check.
RESULT - the result of the operation : 0 indicates the file exists, 1 indicates the string does exist.
STRING- the string to look for.

STDERRCONTAINS(COMMAND_ID, RESULT, STRING)

This function checks for the existence of string in the trace file output by the process COMMAND_ID. The check is done by a case-sensitive comparison.
This command must be preceded by a call to CMDGETTRACE(..), since the check is done on the QAT side, not an the agent side, so the file first needs to be retrieved from the agent.

COMMAND_ID - the command whose trace file we want to check.
RESULT - the result of the operation : 0 indicates the string exists, 1 indicates the string does exist.
STRING- the string to look for.

GETTRACEPATHS(COMMAND_ID, ENVFILENAME, STDOUTFILENAME, STDERRFILENAME)

This function retrieves the actual path, relative to the agent, of the trace files being generated by the previously started process with id COMMAND_ID. The paths are stored in the variables  ENVFILENAME, STDOUTFILENAME and STDERRFILENAME.
Note, however, these paths will no longer be valid after a call to CMDCLEAN(...) has been made.

COMMAND_ID - the command whose trace file paths we require.
ENVFILENAME,STDOUTFILENAME,STDERRFILENAME - the result of the operation will populate these variables with the expected values.