TestUnit TestHarness.lsl

From Second Life Wiki
Revision as of 11:03, 12 April 2008 by Uzume Grigorovich (talk | contribs) (typos)
Jump to navigation Jump to search

<lsl> /////////////////////////////////////////////////////////////////////////////////// /////// /////// /////// /////// TestUnit_TestHarness /////// /////// /////// /////// This is the interface script that talks to the Coordinator. It should be included /////// in each TestUnit. It communicates with the TestScripts via linked message. /////// /////// //////////////////////////////////////////////////////////////////////////////////////

//TestUnit_TestHarness .1 -> initial framework 6.23.2007 //TestUnit_TestHarness .2 -> testing and minor bugfixes 7.2.2007


////////////////////////////////////////////////////////////////////////////////////// // General Specification for TestUnit from https://wiki.secondlife.com/wiki/LSLTest //////////////////////////////////////////////////////////////////////////////////////

//Each test unit will have a small amount of boiler plate code to talk to the controller and understand the communication enough to change to another channel, start tests, and report test results. //[edit] Requirements

// * All test units reset to a default test broadcast channel of 0. // * All test units will be in a test group and the unit knows the group name. // * All test units have a name. // * Register to a coordinator on announcement of registration. // * Change communication channel on request of the coordinator // * Run its tests on the request of the coordinator // * Report test results with multiple levels of output // o verbose: everything // o normal: failures and summary information // o quiet: summary information only


////////////////////////////////////////////////////////////////////////////////////// // // Command Protocol // ////////////////////////////////////////////////////////////////////////////////////// // // All commands, input,output,chat, or linked message will be :: separated // lists in string form. // ////////////////////////////////////////////// // CHAT commands ////////////////////////////////////////////// // // Chat commands will be on the specified controlChannel // //////// INPUT /////////// // // The first element of a chat command can be only one of three things. // // ALL - A general indicator for all testUnits to process the command // unitName - The specific name of this unit // groupName - The specific name of the group this unit belongs to // // This first element of the chat input is parsed, and the remainder of the command // is sent to the parseCommand function. The follow are the current input commands // //// // Reset - sends link message toAllChannel calling for reset, and then resets this script // format example -> ALL::Reset // // RegisterUnit - sends out chat on controlChannel unit registration information // format example -> ALL::RegisterUnit // // RunTest - clears passFail and sends out linked message to TestScript // format example -> ALL::RunTest // // Report - sends out linked message to TestScript with broadcastChannel information // format example -> ALL::Report // // SetReportType - sends out linked message to TestScript with Report Level change // format example -> ALL::SetReportType::NORMAL // // UpdateUnitStatus - sends out unit status information on chat controlChannel // format example -> ALL::UpdateUnitStatus // // SetControlChannel - changes controlChannel to value provided // format example -> ALL::SetControlChannel::-1234 // // //////// OUTPUT /////////// // // Registration - Response to RegisterUnit command, send registration information to Coordinator // format example -> Registration::unitKey::00000-0000-0000-00000::unitName::TestUnit1::groupName::Group1 // // UpdateUnitStatus - Response to request to send out unit status information // format example -> UpdateUnitStatus::unitKey::00000-0000-0000-00000::unitStatus::PASS // // // ////////////////////////////////////////////// // LINK MESSAGE commands ////////////////////////////////////////////// // // link message commands will be sent out on the toAllChannel, and recieved on the passFailChannel // //////// INPUT /////////// // // passFail - status of test sent by TestScript // format example -> PASS // //////// OUTPUT /////////// // // RunTest - activation command to start test // format example -> RunTest // // Reset - calls for script resets on toAllChannel // format example -> Reset // // Report - sends channel and report type to TestScript // format example -> Report::controlChannel::0::reportType::NORMAL // /////////////////////////////////////////////////////////////////////////////////////////////////////////////



// Global Variables

integer toAllChannel = -255; // general channel - linked message integer passFailChannel = -355; // test scripts channel for communicating pass/fail - linked message

integer controlChannel = 1234; // command communication channel - chat

integer controlChannelListen; // handler for the listener event

integer debug = 0; // level of debug message integer debugChannel = DEBUG_CHANNEL; // output channel for debug messages

integer notecardLines; // key notecardRequestKey; // notecard globals key notecardLineRequest; // notecard stores UnitName and GroupName integer currentNoteLine; //

string groupName = "UNKNOWN"; // name of TestUnit group, used by Coordinator

                                      // to select multiple units simultaneously 

string unitName = "UNKNOWN"; // name of this TestUnit, used by Coordinator

                                      // to select this unit specifically 

string reportType = "NORMAL"; // determines length and content of report type

                                      // NORMAL - failures and summary information
                                      // QUITE - summary information only
                                      // VERBOSE - everything

string passFail = "FAIL"; // current status of test script

                                      // FAIL - default until successful completion of test
                                      // PASS - successful test completed
                                      

////////////////////////////////////////////////////////////////////////////////////////////////// ////////// ////////// Function: ParseCommand ////////// ////////// Input: string message - command to be parsed ////////// ////////// Output: no return value ////////// ////////// Purpose: This function calls various other functions or sets globals ////////// depending on message string. Allows external command calls ////////// from chat controlChannel ////////// ////////// Issues: no known issues ////////// ////////// ///////////////////////////////////////////////////////////////////////////////////////////////// ParseCommand(string message) {

   if(debug > 1)llSay(debugChannel, llGetScriptName()+ "->ParseCommand: " + message);
       
   //reset all scripts 
   if(message == "reset")
   {
       //broadcast to other scripts reset command
       llMessageLinked(LINK_SET, toAllChannel, "reset", NULL_KEY); 
       //reset this script as well 
       llResetScript();                   
   }
   
   //RegisterUnit()
   else if(message == "RegisterUnit")
   {
       //Example output on controlChannel -> Registration::unitKey::00000-0000-0000-00000::unitName::TestUnit1::groupName::Group1
       llSay(controlChannel, "Registration::unitKey::" + (string)llGetKey() 
                                        + "::unitName::" + unitName
                                        + "::groupName::" + groupName);    
       
       llMessageLinked(LINK_SET, toAllChannel, "Registered", NULL_KEY);
                                             
   }
   //RunTest()
   else if(message == "RunTest")
   {
       //send link message on general channel initiating Test Scripts
       llMessageLinked(LINK_SET, toAllChannel, "RunTest", NULL_KEY);
   }
   //Report()
   else if(message == "Report")
   {
       //send link message on general channel initiating report function from Test Scripts
       //Example output on toAllChannel channel -> Report::controlChannel::0::reportType::NORMAL
       llMessageLinked(LINK_SET, toAllChannel, "Report::controlChannel::" + (string)controlChannel
                                            + "::reportType::" + reportType, NULL_KEY);
   }
   else if(llSubStringIndex(message, "SetReportType::") != -1)
   {
       //parse value from string by deleting message upto index of ::
       //and set global reportType variable
       reportType = llDeleteSubString( message, 0, llSubStringIndex(message, "::") + 1);
   }    
   // UpdateUnitStatus()
   else if(message == "UpdateUnitStatus")
   {
       //send chat message on control channel updating Coordinator with unit test status
       //Example output on control channel -> UpdateUnitStatus::unitKey::00000-0000-0000-00000::unitStatus::PASS
       llSay(controlChannel, "UpdateUnitStatus::unitKey::" + (string)llGetKey() + "::unitStatus::" + passFail );        
   }   
   
   //SetControlChannel()
   //example SetControlChannel::1
   else if(llSubStringIndex(message, "SetControlChannel::") != -1)
   {
       //parse value from string by deleting message upto index of ::
       //and set global controlChannel variable
       controlChannel = (integer)llDeleteSubString( message, 0, llSubStringIndex(message, "::") + 1);
       ActivateUnit();
   }
   

} //end ParseCommand

////////////////////////////////////////////////////////////////////////////////////////////////// ////////// ////////// Function: Initialize ////////// ////////// Input: no input parameters ////////// ////////// Output: no return value ////////// ////////// Purpose: This function initializes any variables or functions necessary ////////// to get us started ////////// ////////// Issues: no known issues ////////// ////////// ///////////////////////////////////////////////////////////////////////////////////////////////// Initialize() {

   //initiate data server call to begin reading notecard
   notecardRequestKey = llGetNumberOfNotecardLines("TestUnit_nc");

}

////////////////////////////////////////////////////////////////////////////////////////////////// ////////// ////////// Function: ActivateUnit ////////// ////////// Input: no input parameters ////////// ////////// Output: no return value ////////// ////////// Purpose: This function activates any variables or functions necessary to get ////////// us running ////////// ////////// Issues: no known issues ////////// ////////// ///////////////////////////////////////////////////////////////////////////////////////////////// ActivateUnit() {

   //remove possible listeners
   llListenRemove(controlChannel);
   //create new listeners
   controlChannelListen = llListen(controlChannel,"",NULL_KEY,"");

}

/////////////////////////////////////////////////////////////////////////////////////// //STATE STATE STATE STATE STATE STATE STATE STATE STATE STATE STATE STATE STATE STATE// /////////////////////////////////////////////////////////////////////////////////////// // // // // // DEFAULT STATE // // // // // /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// default { /////////////////////////////////////////////////////// // State Entry of default state // ///////////////////////////////////////////////////////

  state_entry()
   {
       Initialize();
   }

//////////////////////////////////////////////////////// // On Rez of default state // ////////////////////////////////////////////////////////

   on_rez(integer start_param)
   {
       Initialize();
   }

/////////////////////////////////////////////////////// // Listen of default state // ///////////////////////////////////////////////////////

   listen(integer channel, string name, key id, string message)
   {
       
    if(debug > 0){llSay(debugChannel, llGetScriptName()+ ":listen:" + message);}
    if(debug > 0){llSay(debugChannel, llGetScriptName()+ ":channel:" + (string)channel);}
       
   //from Coordinator
   if(channel == controlChannel)
   {
       //parse :: separated list
       list commandCheck = llParseString2List( message, ["::"], [""] );
       
       //expect ALL, groupName, or unitName before first ::
       //Example ALL::RegisterUnit
       if( ( llList2String( commandCheck, 0 ) == "ALL" )
        || ( llList2String( commandCheck, 0 ) == groupName )
        || ( llList2String( commandCheck, 0 ) == unitName ) )
        {
            //send message to ParseCommand
                        //in string format
                                            // leave out variable before first ::
                                                                        //and send rest of message to last list element
                                            // put it back together with a :: separators
           ParseCommand(llDumpList2String( 
                                           llList2List(commandCheck, 1, 
                                                                        llGetListLength(commandCheck) - 1 ) 
                                          , "::" )
                        ); //end parseCommand
        } // end || if   
   } //end channel if
   

} //end of listen

/////////////////////////////////////////////////////// // Link Message of default state // ///////////////////////////////////////////////////////

   link_message(integer sender_number, integer number, string message, key id)
   {
       //if link message is on the correct channel
       if(number == passFailChannel)
       {
           //update the passFail status with incoming message
           passFail = message;
           //notify Coordinator of new status for this unit
           ParseCommand("UpdateUnitStatus");
           
       }
       
   } //end of link message
   

/////////////////////////////////////////////////////// // data server of default // ///////////////////////////////////////////////////////

   dataserver(key queryid, string data)
   {
       if(queryid == notecardRequestKey) // line number request
       {
           notecardLines = (integer)data;
           currentNoteLine = 0;
           notecardLineRequest = llGetNotecardLine("TestUnit_nc", currentNoteLine);
       } //end line number request
       
       if(queryid == notecardLineRequest) //reading a line from the notecard
       {
           // if the string "UnitName:" exists in the data string, parse the unitName from between the []
           if(llSubStringIndex(data,"UnitName:") > -1)
           {
               unitName = llGetSubString(data, llSubStringIndex(data,"[") + 1,llSubStringIndex(data,"]") - 1);                
           }
           // if the string "GroupName:" exists in the data string, parse the groupName from between the []
           else if(llSubStringIndex(data,"GroupName:") > -1)
           {
               groupName = llGetSubString(data, llSubStringIndex(data,"[") + 1,llSubStringIndex(data,"]") - 1);
           }            
           
           //if additional lines on the notecard
           if(currentNoteLine < notecardLines - 1)
           {
               currentNoteLine += 1;
               //initiate another line request from the dataserver
               notecardLineRequest = llGetNotecardLine("TestUnit_nc", currentNoteLine);
           }else
           {
               // Done setting up, turn on listener
               ActivateUnit();
           }
           
       } //end line request
   } //end data server
   


} // end default </lsl>