The TestStand Application Manager supports processing custom command line arguments through the ProcessUserCommandLineArguments event. This can prove useful when automating test execution from a CI server.
This example is similar to the LabWindows/CVI Basic User Interface, but has been modified to accept the following command line arguments:
Option | Purpose |
---|---|
/SimulateFailure <failures> | When used with the included example sequence file, this suppresses the simulation dialog and instead simulate failures as specified. This argument accepts the following parameters:
|
This example demonstrates the following concepts:
HRESULT CVICALLBACK ApplicationMgr_OnProcessUserCommandLineArguments(CAObjHandle caServerObjHandle, void *caCallbackData, VBOOL processCommand, TSUIObj_Strings arguments, long *currentArgument, enum TSUIEnum_ProcessCommandLineErrors *errorProcessing, char **errorMessage) { int error = 0; long numArgs = 0; int offset = 0; char *currentArg = NULL; char **simFails = NULL; tsErrChk(TSUISUPP_StringsGetCount ((CAObjHandle)arguments, &errorInfo, &numArgs)); tsErrChk(TSUISUPP_StringsGetItem ((CAObjHandle)arguments, &errorInfo, *currentArgument, ¤tArg)); if (strcmp(currentArg, "/SimulateFailure") == 0) { *currentArgument += 1; offset = numArgs - *currentArgument; simFails = calloc (numArgs-*currentArgument, sizeof(char*)); for (int i = 0; i < offset; i++) { tsErrChk(TSUISUPP_StringsGetItem ((CAObjHandle)arguments, &errorInfo, *currentArgument, &simFails[i])); if (strcmp(simFails[i],"Keyboard")==0) { if (processCommand == VTRUE) fails.Keyboard = 4; *currentArgument += 1; } else if (strcmp(simFails[i],"Video")==0) { if (processCommand == VTRUE) fails.Video = 15; *currentArgument += 1; } else if (strcmp(simFails[i],"Power")==0) { if (processCommand == VTRUE) fails.Power = VTRUE; *currentArgument += 1; } else if (strcmp(simFails[i],"CPU")==0) { if (processCommand == VTRUE) fails.CPU = VTRUE; *currentArgument += 1; } else if (strcmp(simFails[i],"ROM")==0) { if (processCommand == VTRUE) fails.ROM = VTRUE; *currentArgument += 1; } else if (strcmp(simFails[i],"RAM")==0) { if (processCommand == VTRUE) fails.RAM = VTRUE; *currentArgument += 1; } else { break; } } } else { char buf[1024]; *errorProcessing = TSUIConst_ProcessCommandLineError_CustomError; CA_FreeMemory(*errorMessage); *errorMessage = CA_AllocMemory(sizeof(buf)); Fmt(buf, "%s<%s%s", "Invalid command line argument: ",currentArg); strncpy (*errorMessage, buf, 1024); } Error: free(simFails); DisplayError(error); return error < 0 ? E_FAIL : S_OK; }
static void DisplayError(int errorCode) { if (errorCode < 0) { printf("Error: %d %s",errorCode,errMsg); TSUI_ApplicationMgrSetExitCode (gMainWindow.applicationMgr, NULL, errorCode); } }
tsErrChk( TSUI_ApplicationMgrAddCommandLineArgumentsHelp (gMainWindow.applicationMgr, &errorInfo, "[/SimulateFailure <failures>]", "<failures>: components to fail separated by spaces.\nvalid parameters are: Keyboard, Video, Power, CPU, ROM, & RAM", ""));
HRESULT CVICALLBACK ApplicationMgr_OnUserMessage (CAObjHandle caServerObjHandle, void *caCallbackData, TSUIObj_UIMessage uiMsg) { int error = 0; LPUNKNOWN tempPropObject = 0; CAObjHandle SeqContext = 0; enum TSEnum_UIMessageCodes msgEvent; tsErrChk( TS_UIMessageGetEvent (uiMsg, &errorInfo, &msgEvent)); tsErrChk( TS_UIMessageGetActiveXData (uiMsg, &errorInfo, &tempPropObject)); CA_CreateObjHandleFromInterface (tempPropObject, &IID_IUnknown, 0, LOCALE_NEUTRAL, 0, 0, &SeqContext); if (msgEvent == TS_UIMsg_UserMessageBase +1) { tsErrChk( TS_PropertySetValBoolean ( SeqContext, &errorInfo, "Locals.UiMsgHandled", 0, VTRUE)); tsErrChk( TS_PropertySetValNumber ( SeqContext, &errorInfo, "Locals.KeyboardValue", 0, fails.Keyboard)); tsErrChk( TS_PropertySetValNumber ( SeqContext, &errorInfo, "Locals.VideoValue", 0, fails.Video)); tsErrChk( TS_PropertySetValBoolean ( SeqContext, &errorInfo, "Locals.PowerFail", 0, fails.Power)); tsErrChk( TS_PropertySetValBoolean ( SeqContext, &errorInfo, "Locals.CPUFail", 0, fails.CPU)); tsErrChk( TS_PropertySetValBoolean ( SeqContext, &errorInfo, "Locals.ROMFail", 0, fails.ROM)); tsErrChk( TS_PropertySetValBoolean ( SeqContext, &errorInfo, "Locals.RAMFail", 0, fails.RAM)); } Error: CA_DiscardObjHandle(SeqContext); DisplayError(error); return error < 0 ? E_FAIL : S_OK; }
Note: By default, TestStand shows dialogs under certain conditions. This can cause hangs when automating sequence execution without user input, such as when ran from a CI Server. In order to prevent popups that require user input, configure the following options:
TestStand 2014 SP1 or later
LabWindows/CVI 2015 or later
TestExec /?
TestExec /runEntryPoint "Single Pass" "<ExampleDir>\TestSequence\Computer Motherboard Test Sequence.seq" /SimulateFailure Keyboard Video RAM /quit
TestStand Help: ProcessUserCommandLineArguments Event
TestStand Help: Configuring Sequence Editor and User Interface Startup Options
Example code from the Example Code Exchange in the NI Community is licensed with the MIT license.