Studio:Interfacing Sample
Note: for content related to versions of STRIDE 3.0.0101a and earlier, please refer to Autoscript Sample v3.0.0101a
Introduction
The following content relates to the sample files and workspaces installed in %STRIDE_DIR%\Samples\TestScripts\Interfacing. This sample consists of a Visual Studio workspace for building a Windows Off-Target App, sample source code and test scripts, and a STRIDE workspace for sample code execution.
Getting Started
Prerequisites
Before starting the Interfacing Sample, the following prerequisites must be satisfied:
- STRIDE must be installed on the Windows PC to be used in the training, and any required licenses must be present.
- Active State Perl must be installed, and additional perl packages must be downloaded and installed.
- Microsoft Visual Studio 2005 or a later version must be installed. If you do not currently have any version of Visual Studio, we recommend that you install the current free version of Visual Studio Express.
For details and instructions, see Host Installation.
Basic Execution
To begin, open the Visual Studio Solution file in the sample directory. This solution (and corresponding project) were created for Visual Studio 2005. If you have a later version of Visual Studio installed, you should be able to open this solution and it will be automatically upgraded if necessary.
Once you have successfully opened the solution, rebuild it. The build process has custom STRIDE build rules integrated and will produce a STRIDE database, intercept module source files, and an Windows Off-Target App that incorporates the sample source code.
Once the build is complete you can open the STRIDE workspace file and run all scripts using the button. The scripts in this workspace focus on scripting with the ascript object model and do not do any test case generation or reporting. For examples of using the reporter object model to add test case reporting to your scripts, please refer to the Reporting Sample.
Sample Description
Now that you have built the Windows Off-Target App and executed the scripting samples, you can take time to peruse the sample scripts. This section provides a brief description for each category of example scripts. You can execute any of the scripts manually as long as you have the Windows Off-Target App (Interfacing.exe) running.
The main focus of this sample is the use of your SCL qualified interfaces in script code. The STRIDE object that enables this is AutoScript (declared as ascript when injected into Studio's script execution environment). These examples are provided in two functionally equivalent examples. One is in jscript and the other in perl. It is recommended that you try to follow one of the provided examples in whichever language you are most comfortable reading.
Note: This sample does not cover the use of test units in ascript. For examples of how to invoke test units from script code, please refer to the Test Class Sample.
Calling Functions
Shows how to call functions that have been captured and qualified using STRIDE. These scripts make calls to functions that have been implemented in the Windows Off-Target App. The examples shows how to set-up and invoke the functions with a variety of input data types - much of the focus is on how to make use of the AutoScript Dynamic Objects interfaces.
Scalars
Shows how to make calls and receive and return values consisting of simple scalar values (int, float, char, etc.) that are passed by value.
AsynchronousCall
Shows how to make asynchronous function calls and wait for the return status. In this example, we illustrate the asynchronous (or non-blocking) calls to a function using the simple f_cf_int function from the previous example. The ParameterList items are assigned in exactly the same way as with synchronous calls. The call, however, is initiated using CallNonBlocking. The response is retrieved by calling WaitForEvent. By default, WaitForEvent blocks forever until an event is generated (such as function return status or a timer) - but you can change this behavior by setting the WaitTimeoutPeriod value to something nonzero before calling WaitForEvent.
If you want to do other processing in the script while waiting for the function return status (or other event), you can code a polling loop and use the IsEventPending property to check the event queue periodically. The second example here illustrates this technique.
Structs
Shows how to make calls to functions that accept and/or return structures by value.
Arrays
Shows how to make calls to functions that have fixed size arrays in their input arguments. The techniques used here to set individual array members are very similar to those used when working with Sized Pointers.
ArrayDataXfer
Shows how to make use of the AutoScript Bulk Transfer interfaces for setting array data. These bulk transfer interfaces can provide better performance for setting large array payloads since all of the data is transferred to ascript using a single COM interface property assignment. For large array payloads, there can be undesirable COM call overhead performance penalty when using the ascript object model directly to set each array member value one-by-one (since each member will be set with a COM interface property invocation). These methods provide a means to mitigate that overhead.
The bulk data transfer interfaces require that you provide strings that represent an entire array's worth of data - partial data is not allowed. For multidimensional arrays, the data must be stored in the string in row-major order. This example uses the same interfaces and the Array example (above) but the data is assigned using the HexString, B64String, or SafeArray properties.
The first example (f_cf_array_1) requires a 3 element, 1 dimensional array of integers. Our target's integers are 4 bytes, thus 24 hex digits are required to represent the array's data. Each 4 bytes (8 hex characters) in our example represents the integer value 10 in little endian byte order which is appropriate for our windows off-target app.
The next example (f_cf_array_2) requires a 3x3 array of integers. Here we use a base64(see RFC 2045) encoded string which requires 48 B64 characters to represent the 36 bytes of the array. Each element in the array again holds the value 10.
The third example (f_cf_array_3) uses a safearray (also known as a COM array or a VBArray) to set the array elements. JScript does not natively support safearrays for writing/assignment, but the Scripting.Dictionary object provides a means for creating a safe-array from a hash table.
Strings
Shows how to use strings in function calls.
Pointers
Shows examples of basic pointer usage, as documented by scl_ptr. The first three examples show how to assign and read pointed-to values. The last example shows how to set a pointer to NULL. For more information on working with pointers in ascript, refer to this article.
Opaque Pointers
Shows how to call functions that have been qualified with scl_ptr_opaque. When working with opaque pointers, the ascript dynamic objects for that parameter refer to the pointer value and not the pointed-to value (as described in the aformentioned article).
Sized Pointers
Shows how to set-up parameters that have been qualified with scl_ptr_sized. The first example (f_cf_sized_pointer_1) declares a size field in the pragma and the script must correctly set the size field. The second example (f_cf_sized_pointer_2) does not declare a size field, the data is assumed to be fixed size. The next example (f_cf_sized_pointer_3) shows how INOUT sized pointers are returned and how the resulting outpointers are accessed. The fourth example (f_cf_sized_pointer_4) shows how to access OUT sized pointers. In this example, we have also declared the the return value of the function as the size field for the OUT sized pointer. The last example (f_cf_sized_pointer_5) shows how to use RETURN sized pointers.
Unions
Shows how to call functions with union input parameters that have been qualified with scl_union. The first two examples show basic examples of calling discriminated unions. The third example demonstrates the use of an enum discriminant value where scl_union_activate has been used to map enum values to active indexes. The last example shows a simple fixed-active member union.
Values
Shows how to make calls to interfaces with parameters that have been qualified with scl_values. The two examples show how to call interfaces with parameters that have been constrained by an enum or user-defined list of values.
Timeout
All of the synchronous function call examples so far have assumed the device is well-behaved that the functions will return in a reasonable amount of time. If you want to make synchronous calls to a target that might fail to return for any reason (e.g. due to a system fault), then you should consider setting the RspTimeoutPeriod value before making any function calls.
This example shows a simple use case for the call timeout. We call a function that actually sleeps for 20 seconds. Prior to making the call, we have set the RspTimeoutPeriod to 5 seconds. As expected, the function does not return in the specified time period, so ascript throws an exception from the Call method.
Owning Functions
Shows how a function implementation (aka owner) can be scripted. The basic steps to implementing an owner in script are:
- Register for ownership of the function. More specifically, the autoscript method Register() (or OverrideRegister()) must be called.
- Call the autoscript API WaitForEvent(). This will pause execution of the script until a caller invokes the method and the method call will be delivered to this script as an event. The event object's type will be FunctionOwner (subtype of Event). This can be validated in script as the event Type field will have the value "FunctionOwner"
- Handle the call by checking the values of the parameters or setting return values.
- Return to the caller with the autoscript Return() method.
Ownership of five different functions is illustrated by the sample. The first function, f_owning_1() is a very simple interface taking a single int parameter and returning an int. The definition of it, like all the owning functions is found in OwningFunctions.h. The functions f_owning_2(), f_owning_3() and f_owning_4() illustrate owner handling of IN, OUT an INOUT pointers rspectively. Finally, f_owning_5() illustrates owner handling of a function with two parameters.
Sending Messages
Send
Shows how to send messages from script code on the host. These messages are handled by a dedicated thread in the off-target app. This script shows examples of sending several message types (captured via scl_msg): one-way command, two-way command/response, and broadcast.
Receiving Messages
Receive
Shows how to receive messages in script, using the same messages as in the previous example. The messages are sent by code that runs in the off-target app.
Using Constants
The AutoScript object model exposes preprocessor macros present in the compilation units given to the STRIDE compiler. There are a number of rules that determine exactly how the macros are interpreted by the compiler (refer to SCL Language Reference for details). The AutoScript Constants Object exposes the preprocessor macros as a collection of items with name an value properties.
Macros
This shows how to use the Value field to refer to the interpreted value of the declared macro. In many cases, this is just the string representation of the macro as declared in the source code. In some cases, when the expression can be readily interpreted as an arithmetic or logical expression, the result of the expression is returned in the Value field instead. Refer to the corresponding Constants.h source file when reviewing this example.
Using Timers
Both examples show how to create and receive timer events created using Ascript.Timers. Timers are created on a per script basis and only affect the event queue for the executing script in which they were created. Timers are treated as an event in the ascript object model, thus the handling of timers integrates well with other asynchronous processing (e.g. wait for function return status or receiving messages).
OneShot
Shows how to create a simple single-shot timer and wait for it to fire.
Periodic
Shows how to create a periodic timer. We wait for the timer to fire 5 times in this example and then we quit.
Callbacks
This sample shows how to handle C-language callbacks. It illustrates two techniques that can be used in STRIDE: anonymous callbacks and named callbacks. The anonymous callback (also called "default") is used when the logic of the registration function is to be tested. This is usually used to verify that the callback function is called (or notified) at the appropriate times. The named callback technique is used when the callback function itself is the logic to be tested.