TcUnit
1.3.2
¶
TwinCAT unit testing framework. Documentation and examples are available at www.tcunit.org
Interfaces
Function Blocks
-
FB_AdsAssertMessageFormatter
-
FB_AdsLogStringMessageFifoQueue
-
FB_AdsTestResultLogger
-
FB_FileControl
-
FB_StreamBuffer
-
FB_xUnitXmlPublisher
-
FB_TestResults
-
FB_AdjustAssertFailureMessageToMax253CharLength
-
FB_AssertResultStatic
-
FB_AssertArrayResultStatic
-
FB_TcUnitRunner
-
FB_Test
-
FB_TestSuite
-
FB_XmlControl
-
F_AnyToUnionValue
-
F_AnyTypeClassToString
-
F_AssertionTypeToString
-
F_GetCpuCounterAs64bit
-
F_GetTestSuiteNameFromTestInstancePath
-
F_IsAnyEqualToUnionValue
-
F_RemoveInstancePathAndProjectNameFromTestInstancePath
-
IS_TEST_FINISHED
-
RUN
-
RUN_IN_SEQUENCE
-
TCUNIT_ADSLOGSTR
-
TEST
-
TEST_FINISHED
-
TEST_FINISHED_NAMED
-
TEST_ORDERED
-
WRITE_PROTECTED_BOOL
-
WRITE_PROTECTED_BYTE
-
WRITE_PROTECTED_DATE
-
WRITE_PROTECTED_DATE_AND_TIME
-
WRITE_PROTECTED_DINT
-
WRITE_PROTECTED_DWORD
-
WRITE_PROTECTED_INT
-
WRITE_PROTECTED_LREAL
-
WRITE_PROTECTED_REAL
-
WRITE_PROTECTED_SINT
-
WRITE_PROTECTED_STRING
-
WRITE_PROTECTED_WSTRING
-
WRITE_PROTECTED_TIME
-
WRITE_PROTECTED_TIME_OF_DAY
-
WRITE_PROTECTED_UDINT
-
WRITE_PROTECTED_UINT
-
WRITE_PROTECTED_ULINT
-
WRITE_PROTECTED_LWORD
-
WRITE_PROTECTED_LINT
-
WRITE_PROTECTED_USINT
-
WRITE_PROTECTED_WORD
User Datatypes
-
E_AssertionType
-
E_XmlError
-
ST_AdsLogStringMessage
-
ST_AssertResult
-
ST_AssertResultInstances
-
ST_AssertArrayResult
-
ST_AssertArrayResultInstances
-
ST_TestCaseResult
-
ST_TestSuiteResult
-
ST_TestSuiteResults
-
U_ExpectedOrActual
Global Variablelists
Dependencies
-
SysDir
–* – System -
SysFile
–* – System -
Tc2_Standard
–* – Beckhoff Automation GmbH -
Tc2_System
–* – Beckhoff Automation GmbH -
Tc2_Utilities
–* – Beckhoff Automation GmbH
I_TestResultLogger
¶
Methods
LogTestSuiteResults
PUBLIC
¶
Source Code
METHOD PUBLIC LogTestSuiteResults
I_TestResults
¶
Methods
FB_AdsAssertMessageFormatter
Implements: I_AssertMessageFormatter
¶
This
function block is responsible for printing the results of the assertions using the built-in ADSLOGSTR functionality provided by the Tc2_System library. This sends the result using ADS, which is consumed by the error list of Visual Studio.
Methods
Source Code
(*
This function block is responsible for printing the results of the assertions using the built-in
ADSLOGSTR functionality provided by the Tc2_System library. This sends the result using ADS, which
is consumed by the error list of Visual Studio.
*)
FUNCTION_BLOCK FB_AdsAssertMessageFormatter IMPLEMENTS I_AssertMessageFormatter
LogAssertFailure
PUBLIC
¶
Inputs
Source Code
METHOD PUBLIC LogAssertFailure
VAR_INPUT
Expected : T_MaxString;
Actual : T_MaxString;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR
AdjustAssertFailureMessageToMax253CharLength : FB_AdjustAssertFailureMessageToMax253CharLength;
TestInstancePathCleaned : T_MaxString;
TestInstancePathFinal : T_MaxString;
ReturnValue : DINT;
TestInstancePathProcessed : T_MaxString;
MessageProcessed : T_MaxString;
END_VAR
TestInstancePathCleaned := F_RemoveInstancePathAndProjectNameFromTestInstancePath(TestInstancePath);
TestInstancePathFinal := CONCAT(STR1 := 'FAILED TEST $'',
STR2 := TestInstancePathCleaned);
TestInstancePathFinal := CONCAT(STR1 := TestInstancePathFinal,
STR2 := '$'');
TestInstancePathFinal := CONCAT(STR1 := TestInstancePathFinal,
STR2 := ', EXP: ');
TestInstancePathFinal := CONCAT(STR1 := TestInstancePathFinal,
STR2 := Expected);
TestInstancePathFinal := CONCAT(STR1 := TestInstancePathFinal,
STR2 := ', ACT: ');
TestInstancePathFinal := CONCAT(STR1 := TestInstancePathFinal,
STR2 := Actual);
IF LEN(STR := Message) > 0 THEN
TestInstancePathFinal := CONCAT(STR1 := TestInstancePathFinal,
STR2 := ', MSG: %s');
END_IF
AdjustAssertFailureMessageToMax253CharLength(TestInstancePath := TestInstancePathFinal,
TestMessage := Message,
TestInstancePathProcessed => TestInstancePathProcessed,
TestMessageProcessed => MessageProcessed);
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := TestInstancePathProcessed,
StrArg := MessageProcessed);
FB_AdsLogStringMessageFifoQueue
¶
Methods
Source Code
(* This function block is responsible for making sure that the ADSLOGSTR-messages to the ADS-router are transmitted
cyclically and not in a burst. The reason this is necessary is because that if too many messages are sent at the
same time some get lost and are never printed to the error list output
*)
FUNCTION_BLOCK FB_AdsLogStringMessageFifoQueue
VAR
ArrayBuffer : ARRAY[0..((GVL_Param_TcUnit.AdsLogMessageFifoRingBufferSize * (SIZEOF(ST_ADSLogStringMessage) + MEM_RING_BUFFER_INTERNAL_USE_PER_DATA_RECORD)) - 1)] OF BYTE;
MemRingBuffer : FB_MemRingBuffer;
TimerBetweenMessages : TON := (IN := TRUE, PT := TIME_BETWEEN_MESSAGES);
END_VAR
VAR CONSTANT
MEM_RING_BUFFER_INTERNAL_USE_PER_DATA_RECORD : USINT := 4;
TIME_BETWEEN_MESSAGES : TIME := T#10MS;
END_VAR
VAR_TEMP
MessageToBeSent : ST_AdsLogStringMessage;
ErrorGet : BOOL;
ReturnValue : DINT;
END_VAR
TimerBetweenMessages();
IF GetLogCount() > 0 THEN
// Timer has elapsed, print message
IF TimerBetweenMessages.Q THEN
GetAndRemoveLogFromQueue(AdsLogStringMessage => MessageToBeSent,
Error => ErrorGet);
IF NOT ErrorGet THEN
ReturnValue := ADSLOGSTR(msgCtrlMask := MessageToBeSent.MsgCtrlMask,
msgFmtStr := MessageToBeSent.MsgFmtStr,
strArg := MessageToBeSent.StrArg);
END_IF
TimerBetweenMessages(IN := FALSE); // Reset timer
TimerBetweenMessages.IN := TRUE;
END_IF
END_IF
GetAndRemoveLogFromQueue
PRIVATE
¶
Outputs
-
AdsLogStringMessage
-
Error
–Buffer empty
Source Code
(* Reads and removes the oldest message *)
METHOD PRIVATE GetAndRemoveLogFromQueue
VAR_OUTPUT
AdsLogStringMessage : ST_ADSLogStringMessage;
Error : BOOL; // Buffer empty
END_VAR
MemRingBuffer.A_RemoveHead(pRead := ADR(AdsLogStringMessage),
cbRead := SIZEOF(ST_ADSLogStringMessage),
pBuffer := ADR(ArrayBuffer),
cbBuffer := SIZEOF(ArrayBuffer));
Error := NOT MemRingBuffer.bOk;
GetLogCount
PRIVATE
¶
Source Code
METHOD PRIVATE GetLogCount : UDINT
GetLogCount := MemRingBuffer.nCount;
WriteLog
INTERNAL
¶
Inputs
Outputs
-
Error
–Buffer overflow
Source Code
// Writes a new data set into the ring buffer
METHOD INTERNAL WriteLog
VAR_INPUT
MsgCtrlMask : DWORD;
MsgFmtStr : T_MaxString;
StrArg : T_MaxString;
END_VAR
VAR_OUTPUT
Error : BOOL; // Buffer overflow
END_VAR
VAR
AdsLogStringMessage : ST_AdsLogStringMessage;
END_VAR
// Only log message types of ERROR if log extended results is not enabled
IF MsgCtrlMask = ADSLOG_MSGTYPE_ERROR OR GVL_Param_TcUnit.LogExtendedResults THEN
AdsLogStringMessage.MsgCtrlMask := MsgCtrlMask;
AdsLogStringMessage.MsgFmtStr := MsgFmtStr;
AdsLogStringMessage.StrArg := StrArg;
MemRingBuffer.A_AddTail(pWrite := ADR(AdsLogStringMessage),
cbWrite := SIZEOF(ST_AdsLogStringMessage),
pBuffer := ADR(ArrayBuffer),
cbBuffer := SIZEOF(ArrayBuffer));
Error := NOT MemRingBuffer.bOk;
END_IF
FB_AdsTestResultLogger
¶
This
function block reports the results from the tests using the built-in ADSLOGSTR functionality provided by the Tc2_System library. This sends the result using ADS, which is consumed by the "Error List" of Visual Studio (which can print Errors, Warnings and Messages).
Methods
Source Code
(*
This function block reports the results from the tests using the built-in ADSLOGSTR functionality
provided by the Tc2_System library. This sends the result using ADS, which is consumed by the "Error List"
of Visual Studio (which can print Errors, Warnings and Messages).
*)
FUNCTION_BLOCK FB_AdsTestResultLogger IMPLEMENTS I_TestResultLogger
VAR
TestResults : I_TestResults;
PrintingTestSuiteResultNumber : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestSuites);
PrintingTestSuiteTrigger : R_TRIG;
// This flag is set once the final end result has printed
PrintedFinalTestResults : BOOL;
// This flag is set once the test suites result have been printed
PrintedTestSuitesResults : BOOL;
END_VAR
FB_init
BOOL
¶
Inputs
-
bInitRetains
–if TRUE, the retain variables are initialized (warm start / cold start)
-
bInCopyCode
–if TRUE, the instance afterwards gets moved into the copy code (online change)
-
iTestResults
Source Code
METHOD FB_init : BOOL
VAR_INPUT
bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
iTestResults : I_TestResults;
END_VAR
TestResults := iTestResults;
LogTestSuiteResults
PUBLIC
¶
Source Code
METHOD PUBLIC LogTestSuiteResults
VAR
TcUnitTestResults : REFERENCE TO ST_TestSuiteResults;
StringToPrint : T_MaxString;
TestsInTestSuiteCounter : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
MaxNumberOfTestsToPrint : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
VAR CONSTANT
TEST_STATUS_SKIP : STRING := 'SKIP';
TEST_STATUS_PASS : STRING := 'PASS';
TEST_STATUS_FAIL : STRING := 'FAIL';
END_VAR
TcUnitTestResults REF= TestResults.GetTestSuiteResults();
IF PrintingTestSuiteResultNumber <= GVL_TcUnit.NumberOfInitializedTestSuites AND NOT PrintedTestSuitesResults THEN
PrintingTestSuiteTrigger(CLK := GVL_TcUnit.TestSuiteAddresses[PrintingTestSuiteResultNumber]^.AreAllTestsFinished());
IF PrintingTestSuiteTrigger.Q THEN
StringToPrint := CONCAT(STR1 := '| Test suite ID=',
STR2 := UINT_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].Identity));
StringToPrint := CONCAT(STR1 := StringToPrint,
STR2 := ' $'%s$'');
// Print test suite name and ID
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := StringToPrint,
StrArg := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].Name);
// Print number of tests/number of failed tests in test suite
StringToPrint := CONCAT(STR1 := '| ID=',
STR2 := UINT_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].Identity));
StringToPrint := CONCAT(STR1 := StringToPrint,
STR2 := ' number of tests=');
StringToPrint := CONCAT(STR1 := StringToPrint,
STR2 := UINT_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].NumberOfTests));
StringToPrint := CONCAT(STR1 := StringToPrint,
STR2 := ', number of failed tests=');
StringToPrint := CONCAT(STR1 := StringToPrint,
STR2 := UINT_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].NumberOfFailedTests));
StringToPrint := CONCAT(STR1 := StringToPrint,
STR2 := ', duration=');
StringToPrint := CONCAT(STR1 := StringToPrint,
STR2 := LREAL_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].Duration));
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := StringToPrint,
StrArg := '');
// Print error if there are too many tests in the test suite
IF (TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].NumberOfTests > GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite) THEN
MaxNumberOfTestsToPrint := GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite;
ELSE
MaxNumberOfTestsToPrint := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].NumberOfTests;
END_IF
// Iterate and print all tests in test suite
FOR TestsInTestSuiteCounter := 1 TO MaxNumberOfTestsToPrint BY 1 DO
// Print test name
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := '| Test name=%s',
StrArg := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestName);
// Print test class name
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := '| Test class name=%s',
StrArg := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestClassName);
// Print test result/status (SUCCESS, FAILED, SKIPPED) + number of assertions made
IF TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestIsFailed THEN
StringToPrint := CONCAT(STR1 := '| Test status=', STR2 := TEST_STATUS_FAIL);
ELSIF TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestIsSkipped THEN
StringToPrint := CONCAT(STR1 := '| Test status=', STR2 := TEST_STATUS_SKIP);
ELSE
StringToPrint := CONCAT(STR1 := '| Test status=', STR2 := TEST_STATUS_PASS);
END_IF
StringToPrint := CONCAT(STR1 := StringToPrint, STR2 := ', number of asserts=');
StringToPrint := CONCAT(STR1 := StringToPrint, STR2 :=
UINT_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].NumberOfAsserts));
StringToPrint := CONCAT(STR1 := StringToPrint, STR2 := ', duration=');
StringToPrint := CONCAT(STR1 := StringToPrint, STR2 :=
LREAL_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].Duration));
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := StringToPrint,
StrArg := '');
// Print assertion/failure message (if existing)
IF (LEN(STR := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].FailureMessage) > 0) THEN
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := '| Test assert message=%s',
StrArg := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].FailureMessage);
END_IF
// Print assertion/failure type (if existing)
IF TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].FailureType <> E_AssertionType.Type_UNDEFINED THEN
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := '| Test assert type=%s',
StrArg := F_AssertionTypeToString(AssertionType :=
TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].FailureType));
END_IF
END_FOR
// Print error message if there are too many tests in the test suite
IF (TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].NumberOfTests > GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite) THEN
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := 'Tests failed because the number of tests (%s',
StrArg := CONCAT(STR1 := TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].NumberOfTests),
STR2 := CONCAT(STR1 := ') in the test suite $'',
STR2 := CONCAT(STR1 := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].Name,
STR2 := CONCAT(STR1 := '$' are more than is defined in parameter $'GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite$' (',
STR2 := CONCAT(STR1 := UINT_TO_STRING(GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite),
STR2 := '). Please increase this parameter.'))))));
END_IF
IF PrintingTestSuiteResultNumber = GVL_TcUnit.NumberOfInitializedTestSuites THEN
PrintedTestSuitesResults := TRUE;
ELSE
PrintingTestSuiteResultNumber := PrintingTestSuiteResultNumber + 1;
END_IF
PrintingTestSuiteTrigger(CLK := FALSE); // Reset trigger
END_IF
END_IF
// Log end results once all test suites have finished running
IF (GVL_TcUnit.NumberOfInitializedTestSuites = 0 OR PrintingTestSuiteResultNumber = GVL_TcUnit.NumberOfInitializedTestSuites)
AND NOT PrintedFinalTestResults AND TestResults.GetAreTestResultsAvailable() THEN
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := '%s',
StrArg := '| ==========TESTS FINISHED RUNNING==========');
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := '| Test suites: %s',
StrArg := UINT_TO_STRING(TcUnitTestResults.NumberOfTestSuites));
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := '| Tests: %s',
StrArg := UINT_TO_STRING(TcUnitTestResults.NumberOfTestCases));
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := '| Successful tests: %s',
StrArg := UINT_TO_STRING(TcUnitTestResults.NumberOfSuccessfulTestCases));
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := '| Failed tests: %s',
StrArg := UINT_TO_STRING(TcUnitTestResults.NumberOfFailedTestCases));
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := '| Duration: %s',
StrArg := LREAL_TO_STRING(TcUnitTestResults.Duration));
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := '%s',
StrArg := '| ======================================');
PrintedFinalTestResults := TRUE;
END_IF
FB_FileControl
¶
Methods
Source Code
// This functionblock can open, close, read, write and delete files on the local filesystem
FUNCTION_BLOCK FB_FileControl
VAR
FileAccessMode : SysFile.ACCESS_MODE := SysFile.AM_APPEND_PLUS; // Append_Plus creates the file if it doesn't exist yet.
FileHandle : SysFile.SysTypes.RTS_IEC_HANDLE;
END_VAR
Close
PUBLIC
¶
Source Code
// Closes the currently opened file.
METHOD PUBLIC Close : SysFile.SysTypes.RTS_IEC_RESULT;
IF FileHandle <> SysFile.SysTypes.RTS_INVALID_HANDLE THEN
Close := SysFile.SysFileClose(hFile := FileHandle);
ELSE
Close := SysDir.CmpErrors.Errors.ERR_INVALID_HANDLE;
END_IF
Delete
PUBLIC
¶
Inputs
Source Code
// Deletes a file specified by name, if it exists.
METHOD PUBLIC Delete : SysFile.SysTypes.RTS_IEC_RESULT;
VAR_INPUT
// File name can contain an absolute or relative path to the file. Path entries must be separated with a forward slash (/)
FileName : T_MaxString;
END_VAR
Delete := SysFile.SysFileDelete(szFileName := FileName);
FileName
T_MaxString
¶
Open
PUBLIC
¶
Inputs
-
FileName
–File name can contain an absolute or relative path to the file. Path entries must be separated with a Slash (/)
-
FileAccessMode
Source Code
// Opens a file
METHOD PUBLIC Open : SysFile.SysTypes.RTS_IEC_RESULT;
VAR_INPUT
FileName : T_MaxString := 'filepath/output.xml'; // File name can contain an absolute or relative path to the file. Path entries must be separated with a Slash (/)
FileAccessMode : SysFile.ACCESS_MODE := SysFile.ACCESS_MODE.AM_APPEND_PLUS;
END_VAR
FileHandle := SysFile.SysFileOpen(szFile := Filename,
am := FileAccessMode,
pResult := ADR(Open));
Read
PUBLIC
¶
Inputs
-
BufferPointer
–Call with ADR();
-
Size
–Call with SIZEOF();
Outputs
Source Code
// Reads a file from disk into the buffer
METHOD PUBLIC Read : SysFile.SysTypes.RTS_IEC_RESULT;
VAR_INPUT
BufferPointer : POINTER TO BYTE; // Call with ADR();
Size : UDINT; // Call with SIZEOF();
END_VAR
VAR_OUTPUT
FileSize : SysFile.SysTypes.RTS_IEC_SIZE;
END_VAR
IF FileHandle <> SysFile.SysTypes.RTS_INVALID_HANDLE THEN
FileSize := SysFile.SysFileRead(hFile := FileHandle,
pbyBuffer := BufferPointer,
ulSize := Size,
pResult := ADR(Read));
ELSE
Read := SysDir.CmpErrors.Errors.ERR_INVALID_HANDLE;
END_IF
Write
PUBLIC
¶
Inputs
-
BufferPointer
–Call with ADR();
-
Size
–Call with SIZEOF();
Source Code
// Writes the contents of the buffer into a file.
METHOD PUBLIC Write : SysFile.SysTypes.RTS_IEC_RESULT;
VAR_INPUT
BufferPointer : POINTER TO BYTE; // Call with ADR();
Size : UDINT; // Call with SIZEOF();
END_VAR
IF FileHandle <> SysFile.SysTypes.RTS_INVALID_HANDLE THEN
SysFile.SysFileWrite(hFile := FileHandle,
pbyBuffer := BufferPointer,
ulSize := Size,
pResult := ADR(Write));
ELSE
Write := SysDir.CmpErrors.Errors.ERR_INVALID_HANDLE;
END_IF
FB_StreamBuffer
¶
Methods
Properties
Source Code
// This functionblock acts as a stream buffer for use with FB_XmlControl
FUNCTION_BLOCK FB_StreamBuffer
VAR
_PointerToStringBuffer : POINTER TO BYTE;
_BufferSize : UDINT;
_Length : UDINT;
END_VAR
Clear
PUBLIC
¶
Source Code
// Clears the buffer and sets the length to 0
METHOD PUBLIC Clear
VAR
Count : UDINT;
END_VAR
IF (_PointerToStringBuffer = 0) OR (_BufferSize = 0) THEN
RETURN;
END_IF
FOR Count := 0 TO (_BufferSize - 1) DO
_PointerToStringBuffer[Count] := 0;
END_FOR
_Length := 0;
Copy
PUBLIC
¶
Inputs
Outputs
Source Code
// Copies a string from the character buffer
METHOD PUBLIC Copy : T_MaxString
VAR_INPUT
StartPos : UDINT;
EndPos : UDINT;
END_VAR
VAR_OUTPUT
CopyLen : UDINT;
XmlError : E_XmlError;
END_VAR
VAR
Loop : UDINT;
PointerToByteToCopy : POINTER TO BYTE;
PointerToBuffer : POINTER TO BYTE;
CurPos : UDINT;
END_VAR
Loop := 0;
PointerToByteToCopy := ADR(Copy);
PointerToBuffer := _PointerToStringBuffer + StartPos - 1;
WHILE(Loop < SIZEOF(Copy)) AND (StartPos - 1 + Loop < _Length) AND (StartPos + Loop < EndPos) DO
PointerToByteToCopy^ := PointerToBuffer^;
Loop := Loop + 1;
PointerToByteToCopy := ADR(Copy) + Loop;
PointerToBuffer := _PointerToStringBuffer + StartPos + Loop -1;
END_WHILE;
IF Loop = SIZEOF(Copy) THEN
XmlError := E_XmlError.ErrorStringLen;
ELSIF StartPos - 1 + Loop = _Length THEN
XmlError := E_XmlError.ErrorMaxBufferLen;
ELSE
XmlError := E_XmlError.OK;
END_IF;
PointerToByteToCopy^ := 0;
CopyLen := Loop;
CutOff
PUBLIC
¶
Inputs
Outputs
Source Code
METHOD PUBLIC CutOff : T_MaxString
VAR_INPUT
StartPos : UDINT;
END_VAR
VAR_OUTPUT
CutLen : UDINT;
XmlError : E_XmlError;
END_VAR
VAR
Loop : UDINT;
PointerToByteToCut : POINTER TO BYTE;
PointerToByteBuffer : POINTER TO BYTE;
END_VAR
Loop := 0;
PointerToByteToCut := ADR(CutOff);
PointerToByteBuffer := _PointerToStringBuffer + StartPos - 1;
WHILE PointerToByteBuffer^ <> 0 AND(Loop < SIZEOF(CutOff)) AND StartPos -1 + Loop < _Length DO
PointerToByteToCut^ := PointerToByteBuffer^;
Loop := Loop + 1;
PointerToByteToCut := ADR(CutOff) + Loop;
PointerToByteBuffer := _PointerToStringBuffer + StartPos - 1 + Loop;
END_WHILE;
IF PointerToByteBuffer^ = 0 THEN
XmlError := E_XmlError.OK;
ELSIF Loop = SIZEOF(CutOff) THEN
XmlError := E_XmlError.ErrorStringLen;
ELSIF StartPos - 1 + Loop = _Length THEN
XmlError := E_XmlError.ErrorMaxBufferLen;
END_IF;
PointerToByteToCut^ := 0;
_Length := StartPos -1;
PointerToByteBuffer := _PointerToStringBuffer + StartPos - 1;
PointerToByteBuffer^ := 0;
CutLen := Loop;
Find
PUBLIC
¶
Inputs
Source Code
(*
Find a searchstring in the buffer and returns its position.
It's possible to add a preffered startposition within buffer
*)
METHOD PUBLIC Find : UDINT
VAR_INPUT
SearchString : STRING;
StartPos : UDINT;
END_VAR
VAR
Loop : UDINT;
Search : UDINT;
PointerToBuffer : POINTER TO BYTE;
PointerToSearch : POINTER TO BYTE;
END_VAR
Loop := 0;
Search := 0;
PointerToBuffer := _PointerToStringBuffer + StartPos;
PointerToSearch := ADR(SearchString);
WHILE(PointerToSearch^ <> 0 ) AND Loop + StartPos < _Length DO
IF PointerToBuffer^ <> PointerToSearch^ THEN
Loop := Loop + 1;
PointerToBuffer := _PointerToStringBuffer + StartPos + Loop;
PointerToSearch := ADR(SearchString);
Search := 0;
ELSE
Search := Search + 1;
PointerToBuffer := _PointerToStringBuffer + StartPos + Loop + Search;
PointerToSearch := ADR(SearchString ) + Search;
END_IF;
END_WHILE;
Find := Loop + 1 + StartPos;
FindBack
PUBLIC
¶
Inputs
Source Code
METHOD PUBLIC FindBack : UDINT
VAR_INPUT
SearchString : T_MaxString;
END_VAR
VAR
Loop : UDINT;
Search : UDINT;
PointerToBuffer : POINTER TO BYTE;
PointerToSearch : POINTER TO BYTE;
END_VAR
Loop := 0;
Search := 0;
PointerToBuffer := _PointerToStringBuffer + _Length;
PointerToSearch := ADR(SearchString);
WHILE(PointerToSearch^ <> 0) AND Loop < _Length DO
IF PointerToBuffer^ <> PointerToSearch^ THEN
Loop := Loop + 1;
PointerToBuffer := _PointerToStringBuffer + _Length - Loop;
PointerToSearch := ADR(SearchString);
Search := 0;
ELSE
Search := Search + 1;
PointerToBuffer := _PointerToStringBuffer + _Length - Loop + Search;
PointerToSearch := ADR(SearchString ) + Search;
END_IF;
END_WHILE;
FindBack := _Length - Loop + 1;
SearchString
T_MaxString
¶
SetBuffer
PUBLIC
¶
Inputs
-
PointerToBufferAddress
–Set buffer address (ADR ...)
-
SizeOfBuffer
–Set buffer size (SIZEOF ...)
Source Code
METHOD PUBLIC SetBuffer : BOOL;
VAR_INPUT
PointerToBufferAddress : POINTER TO BYTE; // Set buffer address (ADR ...)
SizeOfBuffer : UDINT; // Set buffer size (SIZEOF ...)
END_VAR
IF (PointerToBufferAddress = 0) OR (SizeOfBuffer = 0) THEN
SetBuffer := FALSE;
RETURN;
END_IF;
_BufferSize := SizeOfBuffer;
_PointerToStringBuffer := PointerToBufferAddress;
SetBuffer := TRUE;
Append
T_MaxString
Set
¶
Source Code
ByteIn := ADR(Append);
ByteBuffer := _PointerToStringBuffer + _Length; // set start address
WHILE ByteIn^ <> 0 AND (_Length < _BufferSize ) DO
ByteBuffer^ := ByteIn^; //Copy the 1st byte
_Length := _Length + 1; // set new buffer length
ByteIn := ByteIn + 1; // calculate new start address
ByteBuffer := ByteBuffer + 1; // calculate new start address
END_WHILE;
ByteBuffer := _PointerToStringBuffer + _Length; // String End
ByteBuffer^ := 0; // null terminated string
BufferSize
UDINT
Get
¶
Source Code
BufferSize := _BufferSize;
Length
UDINT
Get/Set
¶
Source Code
Length := _Length;
_Length := Length;
FB_xUnitXmlPublisher
¶
Methods
Source Code
// Publishes test results into an xUnit compatible Xml file
FUNCTION_BLOCK FB_xUnitXmlPublisher IMPLEMENTS I_TestResultLogger
VAR
// Dependency injection via FB_Init
TestResults : I_TestResults;
// File access mode
AccessMode : SysFile.ACCESS_MODE := SysFile.AM_WRITE_PLUS;
File : FB_FileControl;
Xml : FB_XMLControl;
BufferInitialised : BOOL := FALSE;
Buffer : ARRAY [0..(GVL_Param_TcUnit.XUnitBufferSize - 1)] OF BYTE;
WritingTestSuiteResultNumber : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestSuites);
PublishTrigger : R_TRIG;
END_VAR
DeleteOpenWriteClose
PRIVATE
¶
Deletes
the former file (if it exists). Opens the file, writes the buffer and closes it.
Source Code
(*
Deletes the former file (if it exists).
Opens the file, writes the buffer and closes it.
*)
METHOD PRIVATE DeleteOpenWriteClose : SysFile.SysTypes.RTS_IEC_RESULT;
DeleteOpenWriteClose := SysDir.CmpErrors.Errors.ERR_OK;
IF Initialised() THEN
DeleteOpenWriteClose := MAX(DeleteOpenWriteClose, File.Delete(Filename := GVL_Param_TcUnit.xUnitFilePath));
DeleteOpenWriteClose := MAX(DeleteOpenWriteClose, File.Open(Filename := GVL_Param_TcUnit.xUnitFilePath, FileAccessMode := AccessMode));
DeleteOpenWriteClose := MAX(DeleteOpenWriteClose, File.Write(BufferPointer := ADR(Buffer), Xml.Length));
DeleteOpenWriteClose := MAX(DeleteOpenWriteClose, File.Close());
ELSE
DeleteOpenWriteClose := SysDir.CmpErrors.Errors.ERR_NOBUFFER;
END_IF;
FB_Init
BOOL
¶
FB_Init
is always available implicitly AND it is used primarily FOR initialization. The return value is not evaluated. For a specific influence, you can also declare the methods explicitly and provide additional code there with the standard initialization code. You can evaluate the return value.
Inputs
-
iTestResults
–Interface dependency injection
Source Code
(*
FB_Init is always available implicitly AND it is used primarily FOR initialization.
The return value is not evaluated. For a specific influence, you can also declare the
methods explicitly and provide additional code there with the standard initialization
code. You can evaluate the return value.
*)
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
iTestResults : I_TestResults; // Interface dependency injection
END_VAR
// Set buffer and flag
Xml.SetBuffer(PointerToBuffer := ADR(Buffer), SizeOfBuffer := SIZEOF(Buffer));
// Set buffer initialised
BufferInitialised := TRUE;
// Set testresult interface
THIS^.TestResults := iTestResults;
iTestResults
I_TestResults
¶
Interface dependency injection
Initialised
PRIVATE
¶
Source Code
METHOD PRIVATE Initialised : BOOL
Initialised := THIS^.BufferInitialised;
LogTestSuiteResults
PUBLIC
¶
This
method is responsible for the entire generation of the output file. The output of the xml writer is NOT beautified.
When new data is available, feel free to add it to the report
Source Code
(*
This method is responsible for the entire generation of the output file.
The output of the xml writer is NOT beautified.
When new data is available, feel free to add it to the report
*)
METHOD PUBLIC LogTestSuiteResults
VAR
UnitTestResults : REFERENCE TO ST_TestSuiteResults;
CurrentSuiteNumber : UINT;
CurrentTestCount : UINT;
END_VAR
VAR CONSTANT
TEST_STATUS_SKIP : STRING := 'SKIP';
TEST_STATUS_PASS : STRING := 'PASS';
TEST_STATUS_FAIL : STRING := 'FAIL';
END_VAR
UnitTestResults REF= TestResults.GetTestSuiteResults();
// Only publish once if "GVL_Param_TcUnit.xUnitEnablePublish" is enabled and all test results are stored.
PublishTrigger(CLK := (TestResults.GetAreTestResultsAvailable() AND GVL_Param_TcUnit.xUnitEnablePublish));
IF PublishTrigger.Q THEN
// <?xml version="1.0" encoding="UTF-8"?>
Xml.WriteDocumentHeader(Header := '<?xml version="1.0" encoding="UTF-8"?>');
// <testsuites>
Xml.NewTag('testsuites');
Xml.NewParameter('disabled', '');
Xml.NewParameter('failures', UINT_TO_STRING(UnitTestResults.NumberOfFailedTestCases));
Xml.NewParameter('tests', UINT_TO_STRING(UnitTestResults.NumberOfSuccessfulTestCases));
Xml.NewParameter('time', LREAL_TO_STRING(UnitTestResults.Duration));
FOR CurrentSuiteNumber := 1 TO UnitTestResults.NumberOfTestSuites BY 1 DO
// <testsuite>
Xml.NewTag('testsuite');
Xml.NewParameter('id', UINT_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].Identity));
Xml.NewParameter('name', UnitTestResults.TestSuiteResults[CurrentSuiteNumber].name);
Xml.NewParameter('tests', UINT_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].NumberOfTests));
Xml.NewParameter('failures', UINT_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].NumberOfFailedTests));
Xml.NewParameter('time', LREAL_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].Duration));
FOR CurrentTestCount := 1 TO UnitTestResults.TestSuiteResults[CurrentSuiteNumber].NumberOfTests BY 1 DO
// <testcase>
Xml.NewTag('testcase');
Xml.NewParameter('name', UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].TestName);
Xml.NewParameter('classname', UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].TestClassName);
Xml.NewParameter('time', LREAL_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].Duration));
IF UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].TestIsFailed THEN
Xml.NewParameter('status', TEST_STATUS_FAIL);
ELSIF UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].TestIsSkipped THEN
Xml.NewParameter('status', TEST_STATUS_SKIP);
ELSE
Xml.NewParameter('status', TEST_STATUS_PASS);
END_IF
// Determine testcase fail or success
IF UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].FailureType <> E_AssertionType.Type_UNDEFINED THEN
(* In case of fail
<failure message="Values differ" type="BYTE" />
*)
Xml.NewTag('failure');
Xml.NewParameter('message', UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].FailureMessage);
Xml.NewParameter('type', F_AssertionTypeToString(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].FailureType));
// Close failure tag
Xml.CloseTag();
ELSE
// In case of success
Xml.NewTagData('');
END_IF
// Close testcase tag
Xml.CloseTag();
END_FOR
// Close testsuite tag
Xml.CloseTag();
END_FOR
// Close testsuites
Xml.CloseTag();
// Delete, open, save and close the file
DeleteOpenWriteClose();
// Clear the internal buffer
Xml.ClearBuffer();
// Inform user
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
msgFmtStr := '%s',
strArg := '| ==========TEST RESULTS EXPORTED===========');
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
msgFmtStr := '| Location: %s ',
strArg := GVL_Param_TcUnit.xUnitFilePath);
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_HINT,
MsgFmtStr := '%s',
StrArg := '| ======================================');
END_IF
FB_TestResults
¶
Methods
Source Code
// This function block holds results of the complete test run, i.e. results for all test suites
FUNCTION_BLOCK FB_TestResults IMPLEMENTS I_TestResults
VAR
// Test results
TestSuiteResults : ST_TestSuiteResults;
// Misc variables
StoringTestSuiteResultNumber : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestSuites);
StoringTestSuiteTrigger : R_TRIG;
StoredTestSuiteResults : BOOL;
StoredGeneralTestResults : BOOL;
NumberOfTestsToAnalyse : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
VAR_TEMP
TestSuiteName : T_MaxString;
TestName : T_MaxString;
TestsInTestSuiteCounter : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
TestToBeStored : FB_Test;
GeneralTestResultsTestSuitesCounter : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestSuites);
END_VAR
// The body of the function block stores the test results
IF StoringTestSuiteResultNumber <= GVL_TcUnit.NumberOfInitializedTestSuites AND NOT StoredTestSuiteResults THEN
StoringTestSuiteTrigger(CLK := GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.AreAllTestsFinished());
IF StoringTestSuiteTrigger.Q THEN
// Remove everything except the program name + "." + test suite name
TestSuiteName := F_RemoveInstancePathAndProjectNameFromTestInstancePath(TestInstancePath := GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.GetInstancePath());
// Store test suite name and ID
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].Name := TestSuiteName;
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].Identity := StoringTestSuiteResultNumber - 1;
// Store number of tests in test suite
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].NumberOfTests :=
GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.GetNumberOfTests();
// Store number of failed tests in test suite
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].NumberOfFailedTests :=
GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.GetNumberOfFailedTests();
// Store the duration
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].Duration :=
GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.GetDuration();
// Limit the test analyse to the max array limit of 'Tests[]' in FB_TestSuite
NumberOfTestsToAnalyse := GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.GetNumberOfTestsToAnalyse();
// Iterate and print all tests in test suite
FOR TestsInTestSuiteCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO
TestToBeStored := GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.GetTestByPosition(TestsInTestSuiteCounter);
// Store test name
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestName := TestToBeStored.GetName();
// Store test class name
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestClassName :=
F_RemoveInstancePathAndProjectNameFromTestInstancePath(GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.GetInstancePath());
// Store whether the test has failed
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestIsFailed :=
TestToBeStored.IsFailed();
// Store whether the test was skipped
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestIsSkipped :=
TestToBeStored.IsSkipped();
// Store the (first failed) assertion message
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].FailureMessage :=
TestToBeStored.GetAssertionMessage();
// Store the (first failed) assertion type
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].FailureType :=
TestToBeStored.GetAssertionType();
// Store number of assertions made
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].NumberOfAsserts :=
TestToBeStored.GetNumberOfAssertions();
// Store the duration of the test
TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].Duration :=
TestToBeStored.GetDuration();
END_FOR
IF StoringTestSuiteResultNumber = GVL_TcUnit.NumberOfInitializedTestSuites THEN
StoredTestSuiteResults := TRUE;
ELSE
StoringTestSuiteResultNumber := StoringTestSuiteResultNumber + 1;
END_IF
StoringTestSuiteTrigger(CLK := FALSE); // Reset trigger
END_IF
END_IF
(* If all test suites have finished running, store the general test results.
Take care OF the special CASE where no tests have NOT yet been defined *)
IF GVL_TcUnit.NumberOfInitializedTestSuites = 0 AND (NOT StoredGeneralTestResults) THEN
StoredGeneralTestResults := TRUE;
StoredTestSuiteResults := TRUE;
ELSIF StoringTestSuiteResultNumber = GVL_TcUnit.NumberOfInitializedTestSuites AND_THEN
GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.AreAllTestsFinished() AND StoredTestSuiteResults AND (NOT StoredGeneralTestResults) THEN
TestSuiteResults.NumberOfTestSuites := GVL_TcUnit.NumberOfInitializedTestSuites;
GVL_TcUnit.Duration := LWORD_TO_LREAL(F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter) - GVL_TcUnit.StartedAt) * GVL_TcUnit.HundredNanosecondToSecond; // Seconds
TestSuiteResults.Duration := GVL_TcUnit.Duration;
FOR GeneralTestResultsTestSuitesCounter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO
TestSuiteResults.NumberOfTestCases := TestSuiteResults.NumberOfTestCases + TestSuiteResults.TestSuiteResults[GeneralTestResultsTestSuitesCounter].NumberOfTests;
TestSuiteResults.NumberOfSuccessfulTestCases := TestSuiteResults.NumberOfSuccessfulTestCases +
(TestSuiteResults.TestSuiteResults[GeneralTestResultsTestSuitesCounter].NumberOfTests -
TestSuiteResults.TestSuiteResults[GeneralTestResultsTestSuitesCounter].NumberOfFailedTests);
TestSuiteResults.NumberOfFailedTestCases := TestSuiteResults.NumberOfFailedTestCases + TestSuiteResults.TestSuiteResults[GeneralTestResultsTestSuitesCounter].NumberOfFailedTests;
END_FOR
StoredGeneralTestResults := TRUE;
END_IF
GetAreTestResultsAvailable
PUBLIC
¶
Source Code
// Returns whether the storing of the test results is finished
METHOD PUBLIC GetAreTestResultsAvailable : BOOL
GetAreTestResultsAvailable := (StoredTestSuiteResults AND StoredGeneralTestResults);
GetTestSuiteResults
PUBLIC
¶
Source Code
METHOD PUBLIC GetTestSuiteResults : REFERENCE TO ST_TestSuiteResults;
GetTestSuiteResults REF=TestSuiteResults;
FB_AdjustAssertFailureMessageToMax253CharLength
¶
This
function block is responsible for making sure that the asserted test instance path and test message are not loo long. The total printed message can not be more than 253 characters long.
Inputs
Outputs
Source Code
(*
This function block is responsible for making sure that the asserted test instance path and test message are not
loo long. The total printed message can not be more than 253 characters long.
*)
FUNCTION_BLOCK FB_AdjustAssertFailureMessageToMax253CharLength
VAR_INPUT
TestInstancePath : T_MaxString;
TestMessage : T_MaxString;
END_VAR
VAR_OUTPUT
TestInstancePathProcessed : T_MaxString;
TestMessageProcessed : T_MaxString;
END_VAR
VAR_TEMP
TestInstancePathTemporary : T_MaxString;
END_VAR
VAR CONSTANT
MESSAGE_FORMATTED_STRING_MAX_NUMBER_OF_CHARACTERS : INT := 253; // This is actually 254, but if StrArg-argument is used (which it is in TcUnit) it is 253.
TEST_NAME_TOO_LONG : STRING := '...TestName too long';
TEST_MESSAGE_TOO_LONG : STRING := '...TestMsg too long';
END_VAR
// Check if any of the two strings are too long (or the combination of them)
// All OK
IF (LEN(STR := TestInstancePath) + LEN(STR := TestMessage)) <= MESSAGE_FORMATTED_STRING_MAX_NUMBER_OF_CHARACTERS THEN
TestInstancePathProcessed := TestInstancePath;
TestMessageProcessed := TestMessage;
// If test instance path is longer than 253 chars, shorten it down to 253 characters and additionally with the length of the '...TestName too long'. Add the text '...TestName too long' to the test instance path. Leave no characters for the message.
ELSIF LEN(STR := TestInstancePath) > MESSAGE_FORMATTED_STRING_MAX_NUMBER_OF_CHARACTERS THEN
TestInstancePathTemporary := LEFT(STR := TestInstancePath,
SIZE := (MESSAGE_FORMATTED_STRING_MAX_NUMBER_OF_CHARACTERS - LEN(STR := TEST_NAME_TOO_LONG)));
TestInstancePathProcessed := CONCAT(STR1 := TestInstancePathTemporary,
STR2 := TEST_NAME_TOO_LONG);
TestMessageProcessed := '';
// If test message is too long (so we cant fit the text "...TestMsg too long" to the end of it) , shorten it (so that we can fit the text)
ELSIF (MESSAGE_FORMATTED_STRING_MAX_NUMBER_OF_CHARACTERS - LEN(STR := TEST_MESSAGE_TOO_LONG)) >= LEN(STR := TestInstancePath) THEN
TestInstancePathProcessed := TestInstancePath;
TestMessageProcessed := LEFT(STR := TestMessage,
SIZE := (MESSAGE_FORMATTED_STRING_MAX_NUMBER_OF_CHARACTERS - LEN(STR := TEST_MESSAGE_TOO_LONG) - LEN(STR := TestInstancePathProcessed)));
TestMessageProcessed := CONCAT(STR1 := TestMessageProcessed,
STR2 := TEST_MESSAGE_TOO_LONG);
// If test instance path is too long (length is between 233 and 253 characters long), shorten it and add the text '...TestName too long'. Leave no characters for the message
ELSE
TestInstancePathTemporary := LEFT(STR := TestInstancePath,
SIZE := (MESSAGE_FORMATTED_STRING_MAX_NUMBER_OF_CHARACTERS - LEN(STR := TEST_NAME_TOO_LONG)));
TestInstancePathProcessed := CONCAT(STR1 := TestInstancePathTemporary,
STR2 := TEST_NAME_TOO_LONG);
TestMessageProcessed := '';
END_IF
FB_AssertResultStatic
¶
This
function block is responsible for keeping track of which asserts that have been made. The reason we need to keep track of these is because if the user does the same assert twice (because of running a test suite over several PLC-cycles) we want to know it so we don't print several times (if the assert fails). An instance of an assert is keyed/identified with the following parameters as key: - Value of expected - Value of actual - Message (string) - Test instance path (string)
Methods
-
AddAssertResult
-
CopyDetectionCountAndResetDetectionCountInThisCycle
-
CreateAssertResultInstance
-
GetDetectionCount
-
GetDetectionCountThisCycle
-
GetNumberOfAssertsForTest
-
ReportResult
Source Code
(*
This function block is responsible for keeping track of which asserts that have been made. The reason we need to
keep track of these is because if the user does the same assert twice (because of running a test suite over several
PLC-cycles) we want to know it so we don't print several times (if the assert fails).
An instance of an assert is keyed/identified with the following parameters as key:
- Value of expected
- Value of actual
- Message (string)
- Test instance path (string)
*)
FUNCTION_BLOCK FB_AssertResultStatic
VAR
// The total number of instances of each of the "AssertResults"
AssertResults : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite] OF ST_AssertResult;
// The total number of unique asserts
TotalAsserts : UINT := 0;
// Function block to get the current task cycle
GetCurrentTaskIndex : GETCURTASKINDEX;
// The total number of instances of each of the "AssertResults"
AssertResultInstances : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite] OF ST_AssertResultInstances;
// The last PLC cycle count
CycleCount : UDINT;
// Only run first cycle
FirstCycleExecuted : BOOL;
END_VAR
AddAssertResult
PRIVATE
¶
Inputs
-
ExpectedSize
-
ExpectedTypeClass
-
ExpectedValue
-
ActualSize
-
ActualTypeClass
-
ActualValue
-
Message
-
TestInstancePath
Source Code
METHOD PRIVATE AddAssertResult
VAR_INPUT
ExpectedSize : UDINT;
ExpectedTypeClass : IBaseLibrary.TypeClass;
ExpectedValue : POINTER TO BYTE;
ActualSize : UDINT;
ActualTypeClass : IBaseLibrary.TypeClass;
ActualValue : POINTER TO BYTE;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR_INST
AssertResultOverflow : BOOL := FALSE;
END_VAR
VAR
sErrorString : T_MaxString;
END_VAR
IF TotalAsserts < GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite THEN
TotalAsserts := TotalAsserts + 1;
AssertResults[TotalAsserts].Expected := F_AnyToUnionValue(AnySize := ExpectedSize, AnyTypeClass := ExpectedTypeClass, AnyValue := ExpectedValue);
AssertResults[TotalAsserts].Actual := F_AnyToUnionValue(AnySize := ActualSize, AnyTypeClass := ActualTypeClass, AnyValue := ActualValue);
AssertResults[TotalAsserts].Message := Message;
AssertResults[TotalAsserts].TestInstancePath := TestInstancePath;
ELSE
IF NOT AssertResultOverflow THEN
sErrorString := CONCAT(STR1 := F_GetTestSuiteNameFromTestInstancePath(TestInstancePath := TestInstancePath),
STR2 := '. Max number of assertions exceeded. Check parameter MaxNumberOfAssertsForEachTestSuite.');
GVL_TcUnit.AdsMessageQueue.WriteLog(msgCtrlMask := ADSLOG_MSGTYPE_ERROR,
msgFmtStr := sErrorString,
strArg := '');
AssertResultOverflow := TRUE;
END_IF
END_IF
CopyDetectionCountAndResetDetectionCountInThisCycle
PRIVATE
¶
Source Code
METHOD PRIVATE CopyDetectionCountAndResetDetectionCountInThisCycle
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
AssertResultInstances[IteratorCounter].DetectionCount := AssertResultInstances[IteratorCounter].DetectionCountThisCycle;
AssertResultInstances[IteratorCounter].DetectionCountThisCycle := 0;
END_FOR
CreateAssertResultInstance
PRIVATE
¶
Inputs
-
ExpectedSize
-
ExpectedTypeClass
-
ExpectedValue
-
ActualSize
-
ActualTypeClass
-
ActualValue
-
Message
-
TestInstancePath
Source Code
METHOD PRIVATE CreateAssertResultInstance
VAR_INPUT
ExpectedSize : UDINT;
ExpectedTypeClass : IBaseLibrary.TypeClass;
ExpectedValue : POINTER TO BYTE;
ActualSize : UDINT;
ActualTypeClass : IBaseLibrary.TypeClass;
ActualValue : POINTER TO BYTE;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
IF AssertResultInstances[IteratorCounter].DetectionCount = 0 AND
AssertResultInstances[IteratorCounter].DetectionCountThisCycle = 0 THEN // Find first free spot
AssertResultInstances[IteratorCounter].AssertResult.Expected := F_AnyToUnionValue(AnySize := ExpectedSize, AnyTypeClass := ExpectedTypeClass, AnyValue := ExpectedValue);
AssertResultInstances[IteratorCounter].AssertResult.Actual := F_AnyToUnionValue(AnySize := ActualSize, AnyTypeClass := ActualTypeClass, AnyValue := ActualValue);
AssertResultInstances[IteratorCounter].AssertResult.Message := Message;
AssertResultInstances[IteratorCounter].AssertResult.TestInstancePath := TestInstancePath;
AssertResultInstances[IteratorCounter].DetectionCountThisCycle := 1;
EXIT;
END_IF
END_FOR
GetDetectionCount
PRIVATE
¶
Inputs
-
ExpectedSize
-
ExpectedTypeClass
-
ExpectedValue
-
ActualSize
-
ActualTypeClass
-
ActualValue
-
Message
-
TestInstancePath
Source Code
METHOD PRIVATE GetDetectionCount : UINT
VAR_INPUT
ExpectedSize : UDINT;
ExpectedTypeClass : IBaseLibrary.TypeClass;
ExpectedValue : POINTER TO BYTE;
ActualSize : UDINT;
ActualTypeClass : IBaseLibrary.TypeClass;
ActualValue : POINTER TO BYTE;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
IF F_IsAnyEqualToUnionValue(ExpectedOrActual := AssertResultInstances[IteratorCounter].AssertResult.Expected,
ExpectedOrActualSize := ExpectedSize,
ExpectedOrActualTypeClass := ExpectedTypeClass,
ExpectedOrActualValue := ExpectedValue) AND
F_IsAnyEqualToUnionValue(ExpectedOrActual := AssertResultInstances[IteratorCounter].AssertResult.Actual,
ExpectedOrActualSize := ActualSize,
ExpectedOrActualTypeClass := ActualTypeClass,
ExpectedOrActualValue := ActualValue) AND
AssertResultInstances[IteratorCounter].AssertResult.Message = Message AND
AssertResultInstances[IteratorCounter].AssertResult.TestInstancePath = TestInstancePath THEN
GetDetectionCount := AssertResultInstances[IteratorCounter].DetectionCount;
END_IF
END_FOR
GetDetectionCountThisCycle
PRIVATE
¶
Inputs
-
ExpectedSize
-
ExpectedTypeClass
-
ExpectedValue
-
ActualSize
-
ActualTypeClass
-
ActualValue
-
Message
-
TestInstancePath
Source Code
METHOD PRIVATE GetDetectionCountThisCycle : UINT
VAR_INPUT
ExpectedSize : UDINT;
ExpectedTypeClass : IBaseLibrary.TypeClass;
ExpectedValue : POINTER TO BYTE;
ActualSize : UDINT;
ActualTypeClass : IBaseLibrary.TypeClass;
ActualValue : POINTER TO BYTE;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
IF F_IsAnyEqualToUnionValue(ExpectedOrActual := AssertResultInstances[IteratorCounter].AssertResult.Expected,
ExpectedOrActualSize := ExpectedSize,
ExpectedOrActualTypeClass := ExpectedTypeClass,
ExpectedOrActualValue := ExpectedValue) AND
F_IsAnyEqualToUnionValue(ExpectedOrActual := AssertResultInstances[IteratorCounter].AssertResult.Actual,
ExpectedOrActualSize := ActualSize,
ExpectedOrActualTypeClass := ActualTypeClass,
ExpectedOrActualValue := ActualValue) AND
AssertResultInstances[IteratorCounter].AssertResult.Message = Message AND
AssertResultInstances[IteratorCounter].AssertResult.Message = TestInstancePath THEN
GetDetectionCountThisCycle := AssertResultInstances[IteratorCounter].DetectionCountThisCycle;
END_IF
END_FOR
GetNumberOfAssertsForTest
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL GetNumberOfAssertsForTest : UINT
VAR_INPUT
CompleteTestInstancePath : T_MaxString;
END_VAR
VAR
Counter : UINT;
NumberOfAsserts : UINT := 0;
END_VAR
IF TotalAsserts > 0 THEN
FOR Counter := 1 TO TotalAsserts BY 1 DO
IF AssertResults[Counter].TestInstancePath = CompleteTestInstancePath THEN
NumberOfAsserts := NumberOfAsserts + 1;
END_IF
END_FOR
END_IF
GetNumberOfAssertsForTest := NumberOfAsserts;
CompleteTestInstancePath
T_MaxString
¶
ReportResult
INTERNAL
¶
This
method is called in every assert and returns whether this particular assert has already been called. The reason one would like to know whether this assert has already been reported or not is to not report it several times to any logging service. Because a test-suite can consist of several tests, and certain tests can require the test to run over several cycles it means that certain asserts could be called several times and thus we need to keep track of which asserts we've already reported. The user of the framework should not need to care for any of this and he/she should be able to call the asserts in any way they find suitable.
To know what assert this is we need to check for the total combination of:
- Test message
- Test instance path
- Expected value
- Actual value
Theoretically we can have a situation where a test has three different asserts, each and one with the same test
message/test instance path/actual value/expected value but called within the same or different cycles. In order for
us to handle all situations we need a simple algorithm that works according to:
- Keep track of how many instances the combination of test message/test instance path/expected value/actual value
we have. So for example, if we have called Assert(Exp := 5, Act := 5, 'Hello there', 'PRG.InstanceTestSuite.Test')
two times in one cycle, we have two instances of that combination. This is done according to:
- Iterate all existing reports.
- If we have a new PLC-cycle, set the current detection-count to zero.
- If new report does not match in any of the above fields, create it (together with current PLC-cycle).
Also store the information that we have one instance of this combination and +1 on the detection-count.
- If new report matches in all of the above, +1 in the detection-count. If this detection-count is larger than
the stored detection-count for this combination, create a new report and add +1 to the storage of
the detection-count.
Inputs
-
ExpectedSize
-
ExpectedTypeClass
-
ExpectedValue
-
ActualSize
-
ActualTypeClass
-
ActualValue
-
Message
-
TestInstancePath
Outputs
Source Code
(*
This method is called in every assert and returns whether this particular assert has already been called.
The reason one would like to know whether this assert has already been reported or not is to not report it several
times to any logging service. Because a test-suite can consist of several tests, and certain tests can require the
test to run over several cycles it means that certain asserts could be called several times and thus we need to
keep track of which asserts we've already reported. The user of the framework should not need to care for any of
this and he/she should be able to call the asserts in any way they find suitable.
To know what assert this is we need to check for the total combination of:
- Test message
- Test instance path
- Expected value
- Actual value
Theoretically we can have a situation where a test has three different asserts, each and one with the same test
message/test instance path/actual value/expected value but called within the same or different cycles. In order for
us to handle all situations we need a simple algorithm that works according to:
- Keep track of how many instances the combination of test message/test instance path/expected value/actual value
we have. So for example, if we have called Assert(Exp := 5, Act := 5, 'Hello there', 'PRG.InstanceTestSuite.Test')
two times in one cycle, we have two instances of that combination. This is done according to:
- Iterate all existing reports.
- If we have a new PLC-cycle, set the current detection-count to zero.
- If new report does not match in any of the above fields, create it (together with current PLC-cycle).
Also store the information that we have one instance of this combination and +1 on the detection-count.
- If new report matches in all of the above, +1 in the detection-count. If this detection-count is larger than
the stored detection-count for this combination, create a new report and add +1 to the storage of
the detection-count.
*)
METHOD INTERNAL ReportResult
VAR_INPUT
ExpectedSize : UDINT;
ExpectedTypeClass : IBaseLibrary.TypeClass;
ExpectedValue : POINTER TO BYTE;
ActualSize : UDINT;
ActualTypeClass : IBaseLibrary.TypeClass;
ActualValue : POINTER TO BYTE;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR_OUTPUT
AlreadyReported : BOOL := FALSE;
END_VAR
VAR
LocationIndex : UINT;
DataTypesNotEquals : BOOL;
DataSizeNotEquals : BOOL;
DataContentNotEquals : BOOL;
CurrentCycleCount : UDINT;
IteratorCounter : UINT;
DetectionCountTemp : UINT := 0;
FoundOne : BOOL;
AdditionalIdenticalAssert : BOOL;
END_VAR
IF NOT FirstCycleExecuted THEN
GetCurrentTaskIndex();
FirstCycleExecuted := TRUE;
END_IF
CurrentCycleCount := TwinCAT_SystemInfoVarList._TaskInfo[GetCurrentTaskIndex.index].CycleCount;
(* Is current cycle the same as the last call to this method?
If not, reset the detection count *)
IF CurrentCycleCount <> CycleCount THEN
CopyDetectionCountAndResetDetectionCountInThisCycle();
END_IF
FOR IteratorCounter := 1 TO TotalAsserts BY 1 DO
IF F_IsAnyEqualToUnionValue(ExpectedOrActual := AssertResultInstances[IteratorCounter].AssertResult.Expected,
ExpectedOrActualSize := ExpectedSize,
ExpectedOrActualTypeClass := ExpectedTypeClass,
ExpectedOrActualValue := ExpectedValue) AND
F_IsAnyEqualToUnionValue(ExpectedOrActual := AssertResultInstances[IteratorCounter].AssertResult.Actual,
ExpectedOrActualSize := ActualSize,
ExpectedOrActualTypeClass := ActualTypeClass,
ExpectedOrActualValue := ActualValue) AND
AssertResultInstances[IteratorCounter].AssertResult.Message = Message AND
AssertResultInstances[IteratorCounter].AssertResult.TestInstancePath = TestInstancePath THEN
AssertResultInstances[IteratorCounter].DetectionCountThisCycle :=
AssertResultInstances[IteratorCounter].DetectionCountThisCycle + 1;
FoundOne := TRUE;
IF AssertResultInstances[IteratorCounter].DetectionCountThisCycle >
AssertResultInstances[IteratorCounter].DetectionCount THEN // This assert is new
AdditionalIdenticalAssert := TRUE;
END_IF
EXIT;
END_IF
END_FOR
// If not found anything, create the first
IF NOT FoundOne THEN
// No existing match found, create a new entry
AddAssertResult(ExpectedSize := ExpectedSize,
ExpectedTypeClass := ExpectedTypeClass,
ExpectedValue := ExpectedValue,
ActualSize := ActualSize,
ActualTypeClass := ActualTypeClass,
ActualValue := ActualValue,
Message := Message, TestInstancePath := TestInstancePath);
CreateAssertResultInstance(ExpectedSize := ExpectedSize,
ExpectedTypeClass := ExpectedTypeClass,
ExpectedValue := ExpectedValue,
ActualSize := ActualSize,
ActualTypeClass := ActualTypeClass,
ActualValue := ActualValue,
Message := Message, TestInstancePath := TestInstancePath);
// An additional instance of this assert needs to be created
ELSIF AdditionalIdenticalAssert THEN
AddAssertResult(ExpectedSize := ExpectedSize,
ExpectedTypeClass := ExpectedTypeClass,
ExpectedValue := ExpectedValue,
ActualSize := ActualSize,
ActualTypeClass := ActualTypeClass,
ActualValue := ActualValue,
Message := Message, TestInstancePath := TestInstancePath);
// In all other cases, this assert has already been reported, we don't need to do anything
ELSE
AlreadyReported := TRUE;
END_IF
// Update the cycle count
CycleCount := TwinCAT_SystemInfoVarList._TaskInfo[GetCurrentTaskIndex.index].CycleCount;
FB_AssertArrayResultStatic
¶
This
function block is responsible for keeping track of which array-asserts that have been made. The reason we need to keep track of these is because if the user does the same assert twice (because of running a test suite over several PLC-cycles) we want to know it so we don't print several times (if the assert fails). An instance of an array-assert is keyed/identified with the following parameters as key: - Array-size (in bytes) of the expecteds - Datatype of the expecteds - Array-size (in bytes) of the actuals - Datatype of the actuals - Message (string) - Test instance path (string)
Methods
-
AddAssertArrayResult
-
CopyDetectionCountAndResetDetectionCountInThisCycle
-
CreateAssertResultInstance
-
GetDetectionCount
-
GetDetectionCountThisCycle
-
GetNumberOfArrayAssertsForTest
-
ReportResult
Source Code
(*
This function block is responsible for keeping track of which array-asserts that have been made.
The reason we need to keep track of these is because if the user does the same assert twice
(because of running a test suite over several PLC-cycles) we want to know it so we don't print several times
(if the assert fails). An instance of an array-assert is keyed/identified with the following parameters as key:
- Array-size (in bytes) of the expecteds
- Datatype of the expecteds
- Array-size (in bytes) of the actuals
- Datatype of the actuals
- Message (string)
- Test instance path (string)
*)
FUNCTION_BLOCK FB_AssertArrayResultStatic
VAR
// The total number of instances of each of the "AssertArrayResults"
AssertArrayResults : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite] OF ST_AssertArrayResult;
// The total number of unique asserts
TotalArrayAsserts : UINT := 0;
// Function block to get the current task cycle
GetCurrentTaskIndex : GETCURTASKINDEX;
// The total number of instances of each of the "AssertArrayResults"
AssertArrayResultInstances : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite] OF ST_AssertArrayResultInstances;
// The last PLC cycle count
CycleCount : UDINT;
// Only run first cycle
FirstCycleExecuted : BOOL;
END_VAR
AddAssertArrayResult
PRIVATE
¶
Inputs
Source Code
METHOD PRIVATE AddAssertArrayResult
VAR_INPUT
ExpectedsSize : UDINT;
ExpectedsTypeClass : IBaseLibrary.TypeClass;
ActualsSize : UDINT;
ActualsTypeClass : IBaseLibrary.TypeClass;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR_INST
AssertResultOverflow : BOOL := FALSE;
END_VAR
VAR
sErrorString : T_MaxString;
END_VAR
IF TotalArrayAsserts < GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite THEN
TotalArrayAsserts := TotalArrayAsserts + 1;
AssertArrayResults[TotalArrayAsserts].ExpectedsSize := ExpectedsSize;
AssertArrayResults[TotalArrayAsserts].ExpectedsTypeClass := ExpectedsTypeClass;
AssertArrayResults[TotalArrayAsserts].ActualsSize := ActualsSize;
AssertArrayResults[TotalArrayAsserts].ActualsTypeClass := ActualsTypeClass;
AssertArrayResults[TotalArrayAsserts].Message := Message;
AssertArrayResults[TotalArrayAsserts].TestInstancePath := TestInstancePath;
ELSE
IF NOT AssertResultOverflow THEN
sErrorString := CONCAT(STR1 := F_GetTestSuiteNameFromTestInstancePath(TestInstancePath := TestInstancePath),
STR2 := '. Max number of assertions exceeded. Check parameter MaxNumberOfAssertsForEachTestSuite.');
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := sErrorString,
StrArg := '');
AssertResultOverflow := TRUE;
END_IF
END_IF
CopyDetectionCountAndResetDetectionCountInThisCycle
PRIVATE
¶
Source Code
METHOD PRIVATE CopyDetectionCountAndResetDetectionCountInThisCycle
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
AssertArrayResultInstances[IteratorCounter].DetectionCount := AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle;
AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle := 0;
END_FOR
CreateAssertResultInstance
PRIVATE
¶
Inputs
Source Code
METHOD PRIVATE CreateAssertResultInstance
VAR_INPUT
ExpectedsSize : UDINT;
ExpectedsTypeClass : IBaseLibrary.TypeClass;
ActualsSize : UDINT;
ActualsTypeClass : IBaseLibrary.TypeClass;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
IF AssertArrayResultInstances[IteratorCounter].DetectionCount = 0 AND
AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle = 0 THEN // Find first free spot
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsSize := ExpectedsSize;
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsTypeClass := ExpectedsTypeClass;
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsSize := ActualsSize;
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsTypeClass := ActualsTypeClass;
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.Message := Message;
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.TestInstancePath := TestInstancePath;
AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle := 1;
EXIT;
END_IF
END_FOR
GetDetectionCount
PRIVATE
¶
Inputs
Source Code
METHOD PRIVATE GetDetectionCount : UINT
VAR_INPUT
ExpectedsSize : UDINT;
ExpectedsTypeClass : IBaseLibrary.TypeClass;
ActualsSize : UDINT;
ActualsTypeClass : IBaseLibrary.TypeClass;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
IF AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsSize = ExpectedsSize AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsTypeClass = ExpectedsTypeClass AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsSize = ActualsSize AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsTypeClass = ActualsTypeClass AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.Message = Message AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.TestInstancePath = TestInstancePath THEN
GetDetectionCount := AssertArrayResultInstances[IteratorCounter].DetectionCount;
END_IF
END_FOR
GetDetectionCountThisCycle
PRIVATE
¶
Inputs
Source Code
METHOD PRIVATE GetDetectionCountThisCycle : UINT
VAR_INPUT
ExpectedsSize : UDINT;
ExpectedsTypeClass : IBaseLibrary.TypeClass;
ActualsSize : UDINT;
ActualsTypeClass : IBaseLibrary.TypeClass;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
END_VAR
FOR IteratorCounter := 1 TO GVL_Param_TcUnit.MaxNumberOfAssertsForEachTestSuite BY 1 DO
IF AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsSize = ExpectedsSize AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsTypeClass = ExpectedsTypeClass AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsSize = ActualsSize AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsTypeClass = ActualsTypeClass AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.Message = Message AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.TestInstancePath = TestInstancePath THEN
GetDetectionCountThisCycle := AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle;
END_IF
END_FOR
GetNumberOfArrayAssertsForTest
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL GetNumberOfArrayAssertsForTest : UINT
VAR_INPUT
CompleteTestInstancePath : T_MaxString;
END_VAR
VAR
Counter : UINT;
NumberOfArrayAsserts : UINT := 0;
END_VAR
IF TotalArrayAsserts > 0 THEN
FOR Counter := 1 TO TotalArrayAsserts BY 1 DO
IF AssertArrayResults[Counter].TestInstancePath = CompleteTestInstancePath THEN
NumberOfArrayAsserts := NumberOfArrayAsserts + 1;
END_IF
END_FOR
END_IF
GetNumberOfArrayAssertsForTest := NumberOfArrayAsserts;
CompleteTestInstancePath
T_MaxString
¶
ReportResult
INTERNAL
¶
This
method is called in every assert and returns whether this particular assert has already been called. The reason one would like to know whether this assert has already been reported or not is to not report it several times to any logging service. Because a test-suite can consist of several tests, and certain tests can require the test to run over several cycles it means that certain asserts could be called several times and thus we need to keep track of which asserts we've already reported. The user of the framework should not need to care for any of this and he/she should be able to call the asserts in any way they find suitable.
To know what assert this is we need to check for the total combination of:
- Test message
- Test instance path
- Expecteds size (in bytes)
- Actuals size (in bytes)
- Expecteds datatype
- Actuals datatype
Theoretically we can have a situation where a test has three different asserts, each and one with the same test
message/test instance path/actuals size&datatype/expecteds size&datatype but called within the same or different
cycles. In order for us to handle all situations we need a simple algorithm that works according to:
- Keep track of how many instances the combination of test message/test instance path/expecteds size&datatype/
actuals size&datatype we have. So for example, if we have called
Assert(Exp := [5,4,3], Act := [5,4,3], 'Hello there', 'PRG.InstanceTestSuite.Test')
two times in one cycle, we have two instances of that combination. This is done according to:
- Iterate all existing reports.
- If we have a new PLC-cycle, set the current detection-count to zero.
- If new report does not match in any of the above fields, create it (together with current PLC-cycle).
Also store the information that we have one instance of this combination and +1 on the detection-count.
- If new report matches in all of the above, +1 in the detection-count. If this detection-count is larger than
the stored detection-count for this combination, create a new report and add +1 to the storage of
the detection-count.
Inputs
Outputs
Source Code
(*
This method is called in every assert and returns whether this particular assert has already been called.
The reason one would like to know whether this assert has already been reported or not is to not report it several
times to any logging service. Because a test-suite can consist of several tests, and certain tests can require the
test to run over several cycles it means that certain asserts could be called several times and thus we need to
keep track of which asserts we've already reported. The user of the framework should not need to care for any of
this and he/she should be able to call the asserts in any way they find suitable.
To know what assert this is we need to check for the total combination of:
- Test message
- Test instance path
- Expecteds size (in bytes)
- Actuals size (in bytes)
- Expecteds datatype
- Actuals datatype
Theoretically we can have a situation where a test has three different asserts, each and one with the same test
message/test instance path/actuals size&datatype/expecteds size&datatype but called within the same or different
cycles. In order for us to handle all situations we need a simple algorithm that works according to:
- Keep track of how many instances the combination of test message/test instance path/expecteds size&datatype/
actuals size&datatype we have. So for example, if we have called
Assert(Exp := [5,4,3], Act := [5,4,3], 'Hello there', 'PRG.InstanceTestSuite.Test')
two times in one cycle, we have two instances of that combination. This is done according to:
- Iterate all existing reports.
- If we have a new PLC-cycle, set the current detection-count to zero.
- If new report does not match in any of the above fields, create it (together with current PLC-cycle).
Also store the information that we have one instance of this combination and +1 on the detection-count.
- If new report matches in all of the above, +1 in the detection-count. If this detection-count is larger than
the stored detection-count for this combination, create a new report and add +1 to the storage of
the detection-count.
*)
METHOD INTERNAL ReportResult
VAR_INPUT
ExpectedsSize : UDINT;
ExpectedsTypeClass : IBaseLibrary.TypeClass;
ActualsSize : UDINT;
ActualsTypeClass : IBaseLibrary.TypeClass;
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_VAR
VAR_OUTPUT
AlreadyReported : BOOL := FALSE;
END_VAR
VAR
LocationIndex : UINT;
DataTypesNotEquals : BOOL;
DataSizeNotEquals : BOOL;
DataContentNotEquals : BOOL;
CurrentCycleCount : UDINT;
IteratorCounter : UINT;
DetectionCountTemp : UINT := 0;
FoundOne : BOOL;
AdditionalIdenticalAssert : BOOL;
END_VAR
IF NOT FirstCycleExecuted THEN
GetCurrentTaskIndex();
FirstCycleExecuted := TRUE;
END_IF
CurrentCycleCount := TwinCAT_SystemInfoVarList._TaskInfo[GetCurrentTaskIndex.index].CycleCount;
(* Is current cycle the same as the last call to this method?
If not, reset the detection count *)
IF CurrentCycleCount <> CycleCount THEN
CopyDetectionCountAndResetDetectionCountInThisCycle();
END_IF
FOR IteratorCounter := 1 TO TotalArrayAsserts BY 1 DO
IF AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsSize = ExpectedsSize AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ExpectedsTypeClass = ExpectedsTypeClass AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsSize = ActualsSize AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.ActualsTypeClass = ActualsTypeClass AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.Message = Message AND
AssertArrayResultInstances[IteratorCounter].AssertArrayResult.TestInstancePath = TestInstancePath THEN
AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle :=
AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle + 1;
FoundOne := TRUE;
IF AssertArrayResultInstances[IteratorCounter].DetectionCountThisCycle >
AssertArrayResultInstances[IteratorCounter].DetectionCount THEN // This assert is new
AdditionalIdenticalAssert := TRUE;
END_IF
EXIT;
END_IF
END_FOR
// If not found anything, create the first
IF NOT FoundOne THEN
// No existing match found, create a new entry
AddAssertArrayResult(ExpectedsSize := ExpectedsSize,
ExpectedsTypeClass := ExpectedsTypeClass,
ActualsSize := ActualsSize,
ActualsTypeClass := ActualsTypeClass,
Message := Message,
TestInstancePath := TestInstancePath);
CreateAssertResultInstance(ExpectedsSize := ExpectedsSize,
ExpectedsTypeClass := ExpectedsTypeClass,
ActualsSize := ActualsSize,
ActualsTypeClass := ActualsTypeClass,
Message := Message,
TestInstancePath := TestInstancePath);
// An additional instance of this assert needs to be created
ELSIF AdditionalIdenticalAssert THEN
AddAssertArrayResult(ExpectedsSize := ExpectedsSize,
ExpectedsTypeClass := ExpectedsTypeClass,
ActualsSize := ActualsSize,
ActualsTypeClass := ActualsTypeClass,
Message := Message,
TestInstancePath := TestInstancePath);
// In all other cases, this assert has already been reported, we don't need to do anything
ELSE
AlreadyReported := TRUE;
END_IF
// Update the cycle count
CycleCount := TwinCAT_SystemInfoVarList._TaskInfo[GetCurrentTaskIndex.index].CycleCount;
FB_TcUnitRunner
¶
Methods
Source Code
// This function block is responsible for holding track of the tests and executing them.
FUNCTION_BLOCK FB_TcUnitRunner
VAR
// Indication of whether all test suites have reported that they are finished
AllTestSuitesFinished : BOOL := FALSE;
AllTestSuitesFinishedTrigger : R_TRIG;
//Test result information
TestResults : FB_TestResults;
(* Prints the results to ADS so that Visual Studio can display the results.
This test result formatter can be replaced with something else than ADS *)
AdsTestResultLogger : FB_AdsTestResultLogger(TestResults);
TestResultLogger : I_TestResultLogger := AdsTestResultLogger;
(* If this flag is set, it means that some external event triggered the
request to abort running the test suites *)
AbortRunningTestSuites : BOOL;
// Publishes a xUnit compatible XML file
xUnitXmlPublisher : FB_xUnitXmlPublisher(TestResults);
XmlTestResultPublisher : I_TestResultLogger := xUnitXmlPublisher;
END_VAR
AbortRunningTestSuiteTests
INTERNAL
¶
Source Code
(* This function sets a flag which makes the runner stop running the tests
in the test suites *)
METHOD INTERNAL AbortRunningTestSuiteTests
AbortRunningTestSuites := TRUE;
RunTestSuiteTests
INTERNAL
¶
Source Code
// This runs all the test suites in parallel
METHOD INTERNAL RunTestSuiteTests
VAR
Counter : UINT := 0;
BusyPrinting : BOOL;
(* We need to hold a temporary state of the statistics
as we don't consider the tests to be completely finished until all test suites have executed completely.
The reason we want to do it this way is because a test suite can run over several cycles. Only once all tests
are finished (which might take many cycles), do we gather correct statistics *)
NumberOfTestSuitesFinished : UINT := 0;
END_VAR
IF GVL_TcUnit.StartedAt = 0 THEN
GVL_TcUnit.StartedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter);
END_IF
// Run TcUnit test suites
IF NOT AllTestSuitesFinished THEN
IF GVL_TcUnit.NumberOfInitializedTestSuites = 0 THEN
AllTestSuitesFinished := TRUE;
ELSIF GVL_TcUnit.NumberOfInitializedTestSuites > 0 THEN
FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO
IF GVL_TcUnit.TestSuiteAddresses[Counter]^.AreAllTestsFinished() THEN
NumberOfTestSuitesFinished := NumberOfTestSuitesFinished + 1;
ELSE
GVL_TcUnit.CurrentTestSuiteBeingCalled := GVL_TcUnit.TestSuiteAddresses[Counter];
GVL_TcUnit.CurrentTestSuiteBeingCalled^.SetStartedAtIfNotSet(Timestamp := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter));
GVL_TcUnit.CurrentTestSuiteBeingCalled^();
// This is not an efficient way to set the duration
IF GVL_TcUnit.TestSuiteAddresses[Counter]^.AreAllTestsFinished() THEN
GVL_TcUnit.CurrentTestSuiteBeingCalled^.CalculateDuration(FinishedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter));
END_IF
END_IF
END_FOR
(* Check if some event triggered an abortion of running the tests, in that case abort it now.
This can be accomplished by setting the result of the test suites run to finished. *)
IF AbortRunningTestSuites THEN
NumberOfTestSuitesFinished := GVL_TcUnit.NumberOfInitializedTestSuites;
END_IF
IF NumberOfTestSuitesFinished = GVL_TcUnit.NumberOfInitializedTestSuites THEN
AllTestSuitesFinished := TRUE;
END_IF
END_IF
END_IF
// Store test suite results continuously
TestResults();
// Log test suite results continuously
TestResultLogger.LogTestSuiteResults();
// Publish the xUnit Xml file once if enabled
XmlTestResultPublisher.LogTestSuiteResults();
// Run the buffered ADS logger
GVL_TcUnit.AdsMessageQueue();
RunTestSuiteTestsInSequence
INTERNAL
¶
Inputs
-
TimeBetweenTestSuitesExecution
–Time delay between a test suite is finished and the next test suite starts
Source Code
// This runs all the test suites in sequence (one after the other)
METHOD INTERNAL RunTestSuiteTestsInSequence
VAR_INPUT
TimeBetweenTestSuitesExecution : TIME; // Time delay between a test suite is finished and the next test suite starts
END_VAR
VAR
BusyPrinting : BOOL;
(* We need to hold a temporary state of the statistics
as we don't consider the tests to be completely finished until all test suites have executed completely.
The reason we want to do it this way is because a test suite can run over several cycles. Only once all tests
are finished (which might take many cycles), do we gather correct statistics *)
NumberOfTestSuitesFinished : UINT := 0;
END_VAR
VAR_INST
(* This variable holds which current test suite is being called, as we are running
each one in a sequence (one by one) *)
CurrentlyRunningTestSuite : UINT := 1;
TimerBetweenExecutionOfTestSuites : TOF;
END_VAR
IF GVL_TcUnit.StartedAt = 0 THEN
GVL_TcUnit.StartedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter);
END_IF
TimerBetweenExecutionOfTestSuites(PT := TimeBetweenTestSuitesExecution);
// Run TcUnit test suites
IF NOT AllTestSuitesFinished THEN
IF GVL_TcUnit.NumberOfInitializedTestSuites = 0 THEN
AllTestSuitesFinished := TRUE;
ELSIF GVL_TcUnit.NumberOfInitializedTestSuites > 0 THEN
IF TimerBetweenExecutionOfTestSuites.Q THEN
TimerBetweenExecutionOfTestSuites.IN := FALSE;
END_IF
IF GVL_TcUnit.TestSuiteAddresses[CurrentlyRunningTestSuite]^.AreAllTestsFinished() THEN
IF CurrentlyRunningTestSuite <> GVL_TcUnit.NumberOfInitializedTestSuites THEN
NumberOfTestSuitesFinished := NumberOfTestSuitesFinished + 1;
CurrentlyRunningTestSuite := CurrentlyRunningTestSuite + 1;
TimerBetweenExecutionOfTestSuites.IN := TRUE;
GVL_TcUnit.CurrentTestSuiteBeingCalled^.CalculateDuration(FinishedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter));
END_IF
ELSIF NOT TimerBetweenExecutionOfTestSuites.Q THEN
GVL_TcUnit.CurrentTestSuiteBeingCalled := GVL_TcUnit.TestSuiteAddresses[CurrentlyRunningTestSuite];
GVL_TcUnit.CurrentTestSuiteBeingCalled^.SetStartedAtIfNotSet(Timestamp := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter));
GVL_TcUnit.CurrentTestSuiteBeingCalled^();
// This is not an efficient way to set the duration
IF GVL_TcUnit.TestSuiteAddresses[CurrentlyRunningTestSuite]^.AreAllTestsFinished() THEN
GVL_TcUnit.CurrentTestSuiteBeingCalled^.CalculateDuration(FinishedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter));
END_IF
END_IF
(* Check if some event triggered an abortion of running the tests, in that case abort it now.
This can be accomplished by setting the result of the test suites run to finished. *)
IF AbortRunningTestSuites THEN
NumberOfTestSuitesFinished := GVL_TcUnit.NumberOfInitializedTestSuites;
END_IF
IF NumberOfTestSuitesFinished = GVL_TcUnit.NumberOfInitializedTestSuites THEN
AllTestSuitesFinished := TRUE;
END_IF
END_IF
END_IF
// Store test suite results continuously
TestResults();
// Log test suite results continuously
TestResultLogger.LogTestSuiteResults();
// Publish the xUnit Xml file once if enabled
XmlTestResultPublisher.LogTestSuiteResults();
// Run the buffered ADS logger
GVL_TcUnit.AdsMessageQueue();
TimeBetweenTestSuitesExecution
TIME
¶
Time delay between a test suite is finished and the next test suite starts
FB_Test
¶
Methods
-
GetAssertionMessage
-
GetAssertionType
-
GetDuration
-
GetName
-
GetNumberOfAssertions
-
GetTestOrder
-
IsFailed
-
IsFinished
-
IsSkipped
-
SetAssertionMessage
-
SetAssertionType
-
SetFailed
-
SetFinishedAndDuration
-
SetName
-
SetNumberOfAssertions
-
SetSkipped
-
SetStartedAtIfNotSet
-
SetTestOrder
Source Code
// This function block holds all data that defines a test.
FUNCTION_BLOCK FB_Test
VAR
TestName : T_MaxString;
TestIsFinished : BOOL;
TestIsSkipped : BOOL; // This is set to true, if test is disabled (by putting the string "disabled_" in front of the test name
NumberOfAssertions : UINT;
(* In which order/sequence relative to the order tests should this test be executed/evaluated.
A value of 0 means it is not defined by TEST_ORDERED() but by un-ordered test (TEST()).
A value <> 0 tells in which order this test will be executed/evaluated. The lower the number, the earlier it will execute. *)
TestOrderNumber : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
// Failure parameters. If TestIsFailed is TRUE, the other parameters will hold values as well
TestIsFailed : BOOL; // Indication of whether this test has at least one failed assert
AssertionMessage : T_MaxString; // Assertion message for the first assertion in this test
AssertionType : E_AssertionType; // Assertion type for the first assertion in this test
StartedAt : LWORD; // Temporary variable to calculate the actual duration of the test, the value holds the cpu cycle counter when a test is started in 100ns precision
Duration : LREAL; // Duration of the test in seconds
END_VAR
GetAssertionMessage
INTERNAL
¶
Source Code
METHOD INTERNAL GetAssertionMessage : T_MaxString
GetAssertionMessage := AssertionMessage;
GetAssertionType
INTERNAL
¶
Source Code
METHOD INTERNAL GetAssertionType : E_AssertionType
GetAssertionType := AssertionType;
GetDuration
INTERNAL
¶
Source Code
METHOD INTERNAL GetDuration : LREAL
GetDuration := Duration;
GetName
INTERNAL
¶
Source Code
METHOD INTERNAL GetName : T_MaxString;
GetName := TestName;
GetNumberOfAssertions
INTERNAL
¶
Source Code
METHOD INTERNAL GetNumberOfAssertions : UINT
GetNumberOfAssertions := NumberOfAssertions;
GetTestOrder
INTERNAL
¶
Source Code
// Gets in which order/sequence relative to the order tests should this test be executed/evaluated.
METHOD INTERNAL GetTestOrder : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
GetTestOrder := TestOrderNumber;
IsFailed
INTERNAL
¶
Source Code
METHOD INTERNAL IsFailed : BOOL
IsFailed := TestIsFailed;
IsFinished
INTERNAL
¶
Source Code
METHOD INTERNAL IsFinished : BOOL
IsFinished := TestIsFinished;
IsSkipped
INTERNAL
¶
Source Code
METHOD INTERNAL IsSkipped : BOOL
IsSkipped := TestIsSkipped;
SetAssertionMessage
INTERNAL
¶
Inputs
Source Code
// Sets the assertion message. If one already exists, it's not overwritten as we keep the first assertion in the test
METHOD INTERNAL SetAssertionMessage
VAR_INPUT
AssertMessage : T_MaxString;
END_VAR
IF LEN(STR := AssertionMessage) = 0 THEN
AssertionMessage := AssertMessage;
END_IF
AssertMessage
T_MaxString
¶
SetAssertionType
INTERNAL
¶
Inputs
Source Code
// Sets the assertion type. If one already exists, it's not overwritten as we keep the first assertion in the test
METHOD INTERNAL SetAssertionType
VAR_INPUT
AssertType : E_AssertionType;
END_VAR
IF AssertionType = E_AssertionType.Type_UNDEFINED THEN
AssertionType := AssertType;
END_IF
AssertType
E_AssertionType
¶
SetFailed
INTERNAL
¶
Source Code
METHOD INTERNAL SetFailed
TestIsFailed := TRUE;
SetFinishedAndDuration
INTERNAL
¶
Inputs
-
FinishedAt
–CPU cycle counter with 100ns precision
Source Code
METHOD INTERNAL SetFinishedAndDuration : BOOL
VAR_INPUT
FinishedAt : LWORD; // CPU cycle counter with 100ns precision
END_VAR
TestIsFinished := TRUE;
Duration := LWORD_TO_LREAL(FinishedAt - StartedAt) * GVL_TcUnit.HundredNanosecondToSecond; // Seconds
FinishedAt
LWORD
¶
CPU cycle counter with 100ns precision
SetName
INTERNAL
¶
SetNumberOfAssertions
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL SetNumberOfAssertions
VAR_INPUT
NoOfAssertions : UINT;
END_VAR
NumberOfAssertions := NoOfAssertions;
NoOfAssertions
UINT
¶
SetSkipped
INTERNAL
¶
Source Code
// Sets the test case to skipped
METHOD INTERNAL SetSkipped
TestIsSkipped := TRUE;
SetStartedAtIfNotSet
INTERNAL
¶
SetTestOrder
INTERNAL
¶
Inputs
Source Code
// Sets in which order/sequence relative to the order tests should this test be executed/evaluated.
METHOD INTERNAL SetTestOrder
VAR_INPUT
OrderNumber : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
TestOrderNumber := OrderNumber;
OrderNumber
UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)
¶
FB_TestSuite
¶
Methods
-
AddTest
-
AddTestNameToInstancePath
-
AreAllTestsFinished
-
AssertArray2dEquals_LREAL
-
AssertArray2dEquals_REAL
-
AssertArray3dEquals_LREAL
-
AssertArray3dEquals_REAL
-
AssertArrayEquals_BOOL
-
AssertArrayEquals_BYTE
-
AssertArrayEquals_DINT
-
AssertArrayEquals_DWORD
-
AssertArrayEquals_INT
-
AssertArrayEquals_LINT
-
AssertArrayEquals_LREAL
-
AssertArrayEquals_LWORD
-
AssertArrayEquals_REAL
-
AssertArrayEquals_SINT
-
AssertArrayEquals_UDINT
-
AssertArrayEquals_UINT
-
AssertArrayEquals_ULINT
-
AssertArrayEquals_USINT
-
AssertArrayEquals_WORD
-
AssertEquals
-
AssertEquals_BOOL
-
AssertEquals_BYTE
-
AssertEquals_DATE
-
AssertEquals_DATE_AND_TIME
-
AssertEquals_DINT
-
AssertEquals_DWORD
-
AssertEquals_INT
-
AssertEquals_LINT
-
AssertEquals_LREAL
-
AssertEquals_LTIME
-
AssertEquals_LWORD
-
AssertEquals_REAL
-
AssertEquals_SINT
-
AssertEquals_STRING
-
AssertEquals_TIME
-
AssertEquals_TIME_OF_DAY
-
AssertEquals_UDINT
-
AssertEquals_UINT
-
AssertEquals_ULINT
-
AssertEquals_USINT
-
AssertEquals_WORD
-
AssertEquals_WSTRING
-
AssertFalse
-
AssertTrue
-
CalculateAndSetNumberOfAssertsForTest
-
CalculateDuration
-
FB_init
-
FindTestSuiteInstancePath
-
GetDuration
-
GetHasStartedRunning
-
GetInstancePath
-
GetNumberOfFailedTests
-
GetNumberOfSkippedTests
-
GetNumberOfSuccessfulTests
-
GetNumberOfTests
-
GetNumberOfTestsToAnalyse
-
GetTestByName
-
GetTestByPosition
-
GetTestOrderNumber
-
IsTestFinished
-
SetStartedAtIfNotSet
-
SetStartedAtTimeBasedOnCpuCounter
-
SetTestFailed
-
SetTestFinished
Source Code
(* This function block is responsible for holding the internal state of the test suite.
Every test suite can have one or more tests, and every test can do one or more asserts.
It's also responsible for providing all the assert-methods for asserting different data types.
Only failed assertions are recorded.
*)
{attribute 'call_after_init'}
{attribute 'reflection'}
FUNCTION_BLOCK FB_TestSuite
VAR
{attribute 'instance-path'}
{attribute 'noinit'}
InstancePath : T_MaxString;
(* We need to have access to specific information of the current task that this test suite
is executed in. This is for instance necessary when we need to know whether a test is
defined already. The definition of a test that is defined already is that we call on it
with the same name twice in the same cycle *)
GetCurrentTaskIndex : GETCURTASKINDEX;
NumberOfTests : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite) := 0;
Tests : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF FB_Test;
(* Rising trigger of whether we have already notified the user of that the test name pointed to by the current
position is a duplicate *)
TestDuplicateNameTrigger : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF R_TRIG;
(* Last cycle count index for a specific test. Used to detect whether this test has already been defined in the
current test suite *)
TestCycleCountIndex : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF UDINT;
AssertResults : FB_AssertResultStatic;
AssertArrayResults : FB_AssertArrayResultStatic;
(* Prints the failed asserts to ADS so that Visual Studio can display the assert message.
This assert formatter can be replaced with something else than ADS *)
AdsAssertMessageFormatter : FB_AdsAssertMessageFormatter;
AssertMessageFormatter : I_AssertMessageFormatter := AdsAssertMessageFormatter;
(* Stores the CPU cycle count with 100ns precision. It also is an indication whether this
test suite has started running its tests (> 0 means it has started) *)
StartedAt : LWORD;
(* Duration it took to run all tests in this testsuite - including the overhead from TcUnit
in seconds *)
Duration : LREAL;
// Number of ordered tests (created by TEST_ORDERED()) that this test suite contains
NumberOfOrderedTests : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
AddTest
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL AddTest : REFERENCE TO FB_Test
VAR_INPUT
TestName : T_MaxString;
IsTestOrdered : BOOL;
END_VAR
VAR
IteratorCounter : UINT;
ErrorMessage : T_MaxString;
TestInstancePath : T_MaxString;
FunctionCallResult : DINT;
CycleCount : UDINT;
TestWithThisNameAlreadyExists : BOOL := FALSE;
LowerCasedTestName : T_MaxString;
TrimmedTestName : T_MaxString;
IgnoreCurrentTestCase : BOOL;
NumberOfTestsToAnalyse : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
GVL_TcUnit.IgnoreCurrentTest := FALSE; // Reset the ignore current test flag
TrimmedTestName := F_LTrim(in := TestName);
TrimmedTestName := F_RTrim(in := TrimmedTestName);
LowerCasedTestName := F_ToLCase(in := TrimmedTestName);
// If test should be disabled, make sure to remove the "disabled_"-part of it from the test name
IF FIND(STR1 := LowerCasedTestName, STR2 := 'disabled_') = 1 THEN
IgnoreCurrentTestCase := TRUE;
TrimmedTestName := DELETE(STR := TrimmedTestName, LEN := LEN(STR := 'disabled_'), POS := 1);
END_IF
GetCurrentTaskIndex(); // Gets the task index of where this function block instance is being run in
(* Check if the test name already exists. Make sure there are no other tests with the same name already
added for this test suite *)
CycleCount := TwinCAT_SystemInfoVarList._TaskInfo[GetCurrentTaskIndex.index].CycleCount;
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
// Iterate all the test names that up to this point have been added for this test suite
FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[IteratorCounter].GetName() = TrimmedTestName THEN
TestWithThisNameAlreadyExists := TRUE;
// Check if a test with this name has already been called in this PLC cycle
IF TestCycleCountIndex[IteratorCounter] = CycleCount THEN
GVL_TcUnit.IgnoreCurrentTest := TRUE;
(* A test with this name already exists for this test suite and has already been called in this cycle.
Send a message notification, but only if we have not done so already. *)
TestDuplicateNameTrigger[IteratorCounter](CLK := TRUE);
IF TestDuplicateNameTrigger[IteratorCounter].Q THEN // Rising edge detected. We have not reported this before
TestInstancePath := F_RemoveInstancePathAndProjectNameFromTestInstancePath(TestInstancePath :=
GVL_TcUnit.CurrentTestSuiteBeingCalled^.GetInstancePath());
ErrorMessage := 'Test with name $'%s$' already exists in test suite $'';
ErrorMessage := CONCAT(STR1 := ErrorMessage, STR2 := TestInstancePath);
ErrorMessage := CONCAT(STR1 := ErrorMessage, STR2 := '$'');
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := ErrorMessage,
StrArg := TrimmedTestName);
END_IF
END_IF
TestCycleCountIndex[IteratorCounter] := CycleCount;
END_IF
END_FOR
IF NOT TestWithThisNameAlreadyExists THEN
// Test has not been found. Add it.
Tests[IteratorCounter].SetName(Name := TrimmedTestName);
NumberOfTests := NumberOfTests + 1;
TestCycleCountIndex[NumberOfTests] := CycleCount;
IF IgnoreCurrentTestCase THEN
Tests[IteratorCounter].SetSkipped();
END_IF
// Extra information to be added if test is ordered (called by TEST_ORDERED())
IF IsTestOrdered THEN
NumberOfOrderedTests := NumberOfOrderedTests + 1;
Tests[IteratorCounter].SetTestOrder(OrderNumber := NumberOfOrderedTests);
END_IF
END_IF
// Check if this test should be disabled
IF IgnoreCurrentTestCase THEN
GVL_TcUnit.IgnoreCurrentTest := TRUE;
RETURN;
END_IF
AddTest REF= GetTestByName(TrimmedTestName);
AddTestNameToInstancePath
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL AddTestNameToInstancePath : T_MaxString
VAR_INPUT
TestInstancePath : T_MaxString;
END_VAR
VAR
CompleteTestInstancePath : T_MaxString;
END_VAR
CompleteTestInstancePath := CONCAT(STR1 := TestInstancePath, STR2 := '@');
AddTestNameToInstancePath := CONCAT(STR1 := CompleteTestInstancePath, STR2 := GVL_TcUnit.CurrentTestNameBeingCalled);
TestInstancePath
T_MaxString
¶
AreAllTestsFinished
PUBLIC
¶
Source Code
METHOD PUBLIC AreAllTestsFinished : BOOL
VAR
Counter : UINT;
GetCurTaskIndex : GETCURTASKINDEX;
NumberOfTestsToAnalyse : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
AreAllTestsFinished := FALSE;
IF NumberOfTests > 0 THEN
AreAllTestsFinished := TRUE;
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
// A test is considered finished if it is finished running (i.e. set by TEST_FINISHED) or if it is skipped/disabled
FOR Counter := 1 TO NumberOfTestsToAnalyse BY 1 DO
AreAllTestsFinished := AreAllTestsFinished AND (Tests[Counter].IsFinished() OR Tests[Counter].IsSkipped());
END_FOR
END_IF
(* If we have been running at least one cycle and no tests are registered, it means that this testsuite is empty
and doesn't contain any test cases. In that case, ignore this testsuite. *)
GetCurTaskIndex();
IF NumberOfTests = 0 AND NOT TwinCAT_SystemInfoVarList._TaskInfo[GetCurTaskIndex.index].FirstCycle AND StartedAt > 0 THEN
AreAllTestsFinished := TRUE;
END_IF
AssertArray2dEquals_LREAL
PUBLIC
¶
Inputs
-
Delta
–The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two LREAL 2D-arrays are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertArray2dEquals_LREAL
VAR_IN_OUT
Expecteds : ARRAY[*,*] OF LREAL; // LREAL 2d array with expected values
Actuals : ARRAY[*,*] OF LREAL; // LREAL 2d array with actual values
END_VAR
VAR_INPUT
Delta : LREAL; // The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
DimensionIndex : USINT; // Index when looping through Dimensions
LowerBoundExpecteds : ARRAY[1..2] OF DINT; // Lower bounds of Expecteds array in each dimension
UpperBoundExpecteds : ARRAY[1..2] OF DINT; // Upper bounds of Expecteds array in each dimension
LowerBoundActuals : ARRAY[1..2] OF DINT; // Lower bounds of Actuals array in each dimension
UpperBoundActuals : ARRAY[1..2] OF DINT; // Upper bounds of Actuals array in each dimension
SizeOfExpecteds : ARRAY[1..2] OF DINT; // Size of Expecteds array in each dimension
SizeOfActuals : ARRAY[1..2] OF DINT; // Size of Actuals array in each dimension
Offset : ARRAY[1..2] OF DINT; // Current Array index offsets from Lower Bound in each dimension
ExpectedArrayIndex : ARRAY[1..2] OF DINT; // Array of current Expected array indexes when looping through arrays
ActualArrayIndex : ARRAY[1..2] OF DINT; // Array of current Actual array indexes when looping through arrays
Expected : LREAL; // Single expected value
Actual : LREAL; // Single actual value
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
(* UPPER_BOUND and LOWER_BOUND require literals for their second parameter,
so they can't be called in a dimension-based loop.
Thus we copy the array dimensions into arrays which accept variable indexes *)
LowerBoundExpecteds[1] := LOWER_BOUND(Expecteds, 1);
UpperBoundExpecteds[1] := UPPER_BOUND(Expecteds, 1);
LowerBoundExpecteds[2] := LOWER_BOUND(Expecteds, 2);
UpperBoundExpecteds[2] := UPPER_BOUND(Expecteds, 2);
LowerBoundActuals[1] := LOWER_BOUND(Actuals, 1);
UpperBoundActuals[1] := UPPER_BOUND(Actuals, 1);
LowerBoundActuals[2] := LOWER_BOUND(Actuals, 2);
UpperBoundActuals[2] := UPPER_BOUND(Actuals, 2);
FOR DimensionIndex := 1 TO 2 DO
SizeOfExpecteds[DimensionIndex] := ABS(UpperBoundExpecteds[DimensionIndex] - LowerBoundExpecteds[DimensionIndex]) + 1;
SizeOfActuals[DimensionIndex] := ABS(UpperBoundActuals[DimensionIndex] - LowerBoundActuals[DimensionIndex]) + 1;
IF SizeOfExpecteds[DimensionIndex] <> SizeOfActuals[DimensionIndex] THEN
Equals := FALSE;
SizeEquals := FALSE;
END_IF
END_FOR
IF SizeEquals THEN
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes in each dimension, which needs to be taken into account. *)
FOR Offset[1] := 0 TO SizeOfExpecteds[1] - 1 DO // Iterate Dimension 1
FOR Offset[2] := 0 TO SizeOfExpecteds[2] - 1 DO // Iterate Dimension 2
// Update index variables
FOR DimensionIndex := 1 TO 2 DO
ExpectedArrayIndex[DimensionIndex] := LowerBoundExpecteds[DimensionIndex] + Offset[DimensionIndex];
ActualArrayIndex[DimensionIndex] := LowerBoundActuals[DimensionIndex] + Offset[DimensionIndex];
END_FOR
// Get array element values
Expected := Expecteds[ExpectedArrayIndex[1], ExpectedArrayIndex[2]];
Actual := Actuals[ActualArrayIndex[1], ActualArrayIndex[2]];
IF ABS(Expected - Actual) > Delta THEN
Equals := FALSE;
EXIT;
END_IF
END_FOR
// Check for loop bailout
IF NOT Equals THEN
EXIT;
END_IF
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds[1] * SizeOfExpecteds[2]),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
ActualsSize := DINT_TO_UDINT(SizeOfActuals[1] * SizeOfActuals[2]),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array2D_LREAL,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = [';
ExpectedString := CONCAT(STR1 := ExpectedString,STR2 := DINT_TO_STRING(LowerBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] (');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := 'x');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ')');
ActualString := 'SIZE = [';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] (');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := 'x');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ')');
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := LREAL_TO_STRING(Expected));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := LREAL_TO_STRING(Actual));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
Delta
LREAL
¶
The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message
T_MaxString
¶
The identifying message for the assertion error
Expecteds
ARRAY[*,*] OF LREAL
¶
LREAL 2d array with expected values
Actuals
ARRAY[*,*] OF LREAL
¶
LREAL 2d array with actual values
AssertArray2dEquals_REAL
PUBLIC
¶
Inputs
-
Delta
–The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two REAL 2D-arrays are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertArray2dEquals_REAL
VAR_IN_OUT
Expecteds : ARRAY[*,*] OF REAL; // REAL 2d array with expected values
Actuals : ARRAY[*,*] OF REAL; // REAL 2d array with actual values
END_VAR
VAR_INPUT
Delta : REAL; // The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
DimensionIndex : USINT; // Index when looping through Dimensions
LowerBoundExpecteds : ARRAY[1..2] OF DINT; // Lower bounds of Expecteds array in each dimension
UpperBoundExpecteds : ARRAY[1..2] OF DINT; // Upper bounds of Expecteds array in each dimension
LowerBoundActuals : ARRAY[1..2] OF DINT; // Lower bounds of Actuals array in each dimension
UpperBoundActuals : ARRAY[1..2] OF DINT; // Upper bounds of Actuals array in each dimension
SizeOfExpecteds : ARRAY[1..2] OF DINT; // Size of Expecteds array in each dimension
SizeOfActuals : ARRAY[1..2] OF DINT; // Size of Actuals array in each dimension
Offset : ARRAY[1..2] OF DINT; // Current Array index offsets from Lower Bound in each dimension
ExpectedArrayIndex : ARRAY[1..2] OF DINT; // Array of current Expected array indexes when looping through arrays
ActualArrayIndex : ARRAY[1..2] OF DINT; // Array of current Actual array indexes when looping through arrays
Expected : REAL; // Single expected value
Actual : REAL; // Single actual value
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
(* UPPER_BOUND and LOWER_BOUND require literals for their second parameter,
so they can't be called in a dimension-based loop.
Thus we copy the ARRAY dimensions into arrays which accept variable indexes *)
LowerBoundExpecteds[1] := LOWER_BOUND(Expecteds, 1);
UpperBoundExpecteds[1] := UPPER_BOUND(Expecteds, 1);
LowerBoundExpecteds[2] := LOWER_BOUND(Expecteds, 2);
UpperBoundExpecteds[2] := UPPER_BOUND(Expecteds, 2);
LowerBoundActuals[1] := LOWER_BOUND(Actuals, 1);
UpperBoundActuals[1] := UPPER_BOUND(Actuals, 1);
LowerBoundActuals[2] := LOWER_BOUND(Actuals, 2);
UpperBoundActuals[2] := UPPER_BOUND(Actuals, 2);
FOR DimensionIndex := 1 TO 2 DO
SizeOfExpecteds[DimensionIndex] := ABS(UpperBoundExpecteds[DimensionIndex] - LowerBoundExpecteds[DimensionIndex]) + 1;
SizeOfActuals[DimensionIndex] := ABS(UpperBoundActuals[DimensionIndex] - LowerBoundActuals[DimensionIndex]) + 1;
IF SizeOfExpecteds[DimensionIndex] <> SizeOfActuals[DimensionIndex] THEN
Equals := FALSE;
SizeEquals := FALSE;
END_IF
END_FOR
IF SizeEquals THEN
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes in each dimension, which needs to be taken into account. *)
FOR Offset[1] := 0 TO SizeOfExpecteds[1] - 1 DO // Iterate Dimension 1
FOR Offset[2] := 0 TO SizeOfExpecteds[2] - 1 DO // Iterate Dimension 2
// Update index variables
FOR DimensionIndex := 1 TO 2 DO
ExpectedArrayIndex[DimensionIndex] := LowerBoundExpecteds[DimensionIndex] + Offset[DimensionIndex];
ActualArrayIndex[DimensionIndex] := LowerBoundActuals[DimensionIndex] + Offset[DimensionIndex];
END_FOR
// Get array element values
Expected := Expecteds[ExpectedArrayIndex[1], ExpectedArrayIndex[2]];
Actual := Actuals[ActualArrayIndex[1], ActualArrayIndex[2]];
IF ABS(Expected - Actual) > Delta THEN
Equals := FALSE;
EXIT;
END_IF
END_FOR
// Check for loop bailout
IF NOT Equals THEN
EXIT;
END_IF
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds[1] * SizeOfExpecteds[2]),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
ActualsSize := DINT_TO_UDINT(SizeOfActuals[1] * SizeOfActuals[2]),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array2D_REAL,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = [';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] (');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := 'x');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ')');
ActualString := 'SIZE = [';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] (');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := 'x');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ')');
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := REAL_TO_STRING(Expected));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := REAL_TO_STRING(Actual));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
Delta
REAL
¶
The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message
T_MaxString
¶
The identifying message for the assertion error
Expecteds
ARRAY[*,*] OF REAL
¶
REAL 2d array with expected values
Actuals
ARRAY[*,*] OF REAL
¶
REAL 2d array with actual values
AssertArray3dEquals_LREAL
PUBLIC
¶
Inputs
-
Delta
–The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two LREAL 3D-arrays are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertArray3dEquals_LREAL
VAR_IN_OUT
Expecteds : ARRAY[*,*,*] OF LREAL; // LREAL 3d array with expected values
Actuals : ARRAY[*,*,*] OF LREAL; // LREAL 3d array with actual values
END_VAR
VAR_INPUT
Delta : LREAL; // The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
DimensionIndex : USINT; // Index when looping through Dimensions
LowerBoundExpecteds : ARRAY[1..3] OF DINT; // Lower bounds of Expecteds array in each dimension
UpperBoundExpecteds : ARRAY[1..3] OF DINT; // Upper bounds of Expecteds array in each dimension
LowerBoundActuals : ARRAY[1..3] OF DINT; // Lower bounds of Actuals array in each dimension
UpperBoundActuals : ARRAY[1..3] OF DINT; // Upper bounds of Actuals array in each dimension
SizeOfExpecteds : ARRAY[1..3] OF DINT; // Size of Expecteds array in each dimension
SizeOfActuals : ARRAY[1..3] OF DINT; // Size of Actuals array in each dimension
Offset : ARRAY[1..3] OF DINT; // Current Array index offsets from Lower Bound in each dimension
ExpectedArrayIndex : ARRAY[1..3] OF DINT; // Array of current Expected array indexes when looping through arrays
ActualArrayIndex : ARRAY[1..3] OF DINT; // Array of current Actual array indexes when looping through arrays
Expected : LREAL; // Single expected value
Actual : LREAL; // Single actual value
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
(* UPPER_BOUND and LOWER_BOUND require literals for their second parameter,
so they can't be called in a dimension-based loop.
Thus we copy the array dimensions into arrays which accept variable indexes *)
LowerBoundExpecteds[1] := LOWER_BOUND(Expecteds, 1);
UpperBoundExpecteds[1] := UPPER_BOUND(Expecteds, 1);
LowerBoundExpecteds[2] := LOWER_BOUND(Expecteds, 2);
UpperBoundExpecteds[2] := UPPER_BOUND(Expecteds, 2);
LowerBoundExpecteds[3] := LOWER_BOUND(Expecteds, 3);
UpperBoundExpecteds[3] := UPPER_BOUND(Expecteds, 3);
LowerBoundActuals[1] := LOWER_BOUND(Actuals, 1);
UpperBoundActuals[1] := UPPER_BOUND(Actuals, 1);
LowerBoundActuals[2] := LOWER_BOUND(Actuals, 2);
UpperBoundActuals[2] := UPPER_BOUND(Actuals, 2);
LowerBoundActuals[3] := LOWER_BOUND(Actuals, 3);
UpperBoundActuals[3] := UPPER_BOUND(Actuals, 3);
FOR DimensionIndex := 1 TO 3 DO
SizeOfExpecteds[DimensionIndex] := ABS(UpperBoundExpecteds[DimensionIndex] - LowerBoundExpecteds[DimensionIndex]) + 1;
SizeOfActuals[DimensionIndex] := ABS(UpperBoundActuals[DimensionIndex] - LowerBoundActuals[DimensionIndex]) + 1;
IF SizeOfExpecteds[DimensionIndex] <> SizeOfActuals[DimensionIndex] THEN
Equals := FALSE;
SizeEquals := FALSE;
END_IF
END_FOR
IF SizeEquals THEN
(* Even though we know that both arrays are equal in size, the three arrays can start at three completely different
indexes in each dimension, which needs to be taken into account. *)
FOR Offset[1] := 0 TO SizeOfExpecteds[1] - 1 DO // Iterate Dimension 1
FOR Offset[2] := 0 TO SizeOfExpecteds[2] - 1 DO // Iterate Dimension 2
FOR Offset[3] := 0 TO SizeOfExpecteds[3] - 1 DO // Iterate Dimension 3
// Update index variables
FOR DimensionIndex := 1 TO 3 DO
ExpectedArrayIndex[DimensionIndex] := LowerBoundExpecteds[DimensionIndex] + Offset[DimensionIndex];
ActualArrayIndex[DimensionIndex] := LowerBoundActuals[DimensionIndex] + Offset[DimensionIndex];
END_FOR
// Get array element values
Expected := Expecteds[ExpectedArrayIndex[1], ExpectedArrayIndex[2], ExpectedArrayIndex[3]];
Actual := Actuals[ActualArrayIndex[1], ActualArrayIndex[2], ActualArrayIndex[3]];
IF ABS(Expected - Actual) > Delta THEN
Equals := FALSE;
EXIT;
END_IF
END_FOR
// Check for loop bailout
IF NOT Equals THEN
EXIT;
END_IF
END_FOR
// Check for loop bailout
IF NOT Equals THEN
EXIT;
END_IF
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds[1] * SizeOfExpecteds[2] * SizeOfExpecteds[3]),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
ActualsSize := DINT_TO_UDINT(SizeOfActuals[1] * SizeOfActuals[2] * SizeOfActuals[3]),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array3D_LREAL,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = [';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] (');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := 'x');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := 'x');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ')');
ActualString := 'SIZE = [';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] (');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := 'x');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := 'x');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ')');
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := LREAL_TO_STRING(Expected) );
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := LREAL_TO_STRING(Actual));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
Delta
LREAL
¶
The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message
T_MaxString
¶
The identifying message for the assertion error
Expecteds
ARRAY[*,*,*] OF LREAL
¶
LREAL 3d array with expected values
Actuals
ARRAY[*,*,*] OF LREAL
¶
LREAL 3d array with actual values
AssertArray3dEquals_REAL
PUBLIC
¶
Inputs
-
Delta
–The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two REAL 3D-arrays are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertArray3dEquals_REAL
VAR_IN_OUT
Expecteds : ARRAY[*,*,*] OF REAL; // REAL 3d array with expected values
Actuals : ARRAY[*,*,*] OF REAL; // REAL 3d array with actual values
END_VAR
VAR_INPUT
Delta : REAL; // The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
DimensionIndex : USINT; // Index when looping through Dimensions
LowerBoundExpecteds : ARRAY[1..3] OF DINT; // Lower bounds of Expecteds array in each dimension
UpperBoundExpecteds : ARRAY[1..3] OF DINT; // Upper bounds of Expecteds array in each dimension
LowerBoundActuals : ARRAY[1..3] OF DINT; // Lower bounds of Actuals array in each dimension
UpperBoundActuals : ARRAY[1..3] OF DINT; // Upper bounds of Actuals array in each dimension
SizeOfExpecteds : ARRAY[1..3] OF DINT; // Size of Expecteds array in each dimension
SizeOfActuals : ARRAY[1..3] OF DINT; // Size of Actuals array in each dimension
Offset : ARRAY[1..3] OF DINT; // Current Array index offsets from Lower Bound in each dimension
ExpectedArrayIndex : ARRAY[1..3] OF DINT; // Array of current Expected array indexes when looping through arrays
ActualArrayIndex : ARRAY[1..3] OF DINT; // Array of current Actual array indexes when looping through arrays
Expected : REAL; // Single expected value
Actual : REAL; // Single actual value
ExpectedValueString : T_MaxString;
ActualValueString : T_MaxString;
FormatString : FB_FormatString; // String formatter for output messages
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
(* UPPER_BOUND and LOWER_BOUND require literals for their second parameter,
so they can't be called in a dimension-based loop.
Thus we copy the array dimensions into arrays which accept variable indexes *)
LowerBoundExpecteds[1] := LOWER_BOUND(Expecteds, 1);
UpperBoundExpecteds[1] := UPPER_BOUND(Expecteds, 1);
LowerBoundExpecteds[2] := LOWER_BOUND(Expecteds, 2);
UpperBoundExpecteds[2] := UPPER_BOUND(Expecteds, 2);
LowerBoundExpecteds[3] := LOWER_BOUND(Expecteds, 3);
UpperBoundExpecteds[3] := UPPER_BOUND(Expecteds, 3);
LowerBoundActuals[1] := LOWER_BOUND(Actuals, 1);
UpperBoundActuals[1] := UPPER_BOUND(Actuals, 1);
LowerBoundActuals[2] := LOWER_BOUND(Actuals, 2);
UpperBoundActuals[2] := UPPER_BOUND(Actuals, 2);
LowerBoundActuals[3] := LOWER_BOUND(Actuals, 3);
UpperBoundActuals[3] := UPPER_BOUND(Actuals, 3);
FOR DimensionIndex := 1 TO 3 DO
SizeOfExpecteds[DimensionIndex] := ABS(UpperBoundExpecteds[DimensionIndex] - LowerBoundExpecteds[DimensionIndex]) + 1;
SizeOfActuals[DimensionIndex] := ABS(UpperBoundActuals[DimensionIndex] - LowerBoundActuals[DimensionIndex]) + 1;
IF SizeOfExpecteds[DimensionIndex] <> SizeOfActuals[DimensionIndex] THEN
Equals := FALSE;
SizeEquals := FALSE;
END_IF
END_FOR
IF SizeEquals THEN
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes in each dimension, which needs to be taken into account. *)
FOR Offset[1] := 0 TO SizeOfExpecteds[1] - 1 DO // Iterate Dimension 1
FOR Offset[2] := 0 TO SizeOfExpecteds[2] - 1 DO // Iterate Dimension 2
FOR Offset[3] := 0 TO SizeOfExpecteds[3] - 1 DO // Iterate Dimension 3
// Update index variables
FOR DimensionIndex := 1 TO 3 DO
ExpectedArrayIndex[DimensionIndex] := LowerBoundExpecteds[DimensionIndex] + Offset[DimensionIndex];
ActualArrayIndex[DimensionIndex] := LowerBoundActuals[DimensionIndex] + Offset[DimensionIndex];
END_FOR
// Get array element values
Expected := Expecteds[ExpectedArrayIndex[1], ExpectedArrayIndex[2], ExpectedArrayIndex[3]];
Actual := Actuals[ActualArrayIndex[1], ActualArrayIndex[2], ActualArrayIndex[3]];
IF ABS(Expected - Actual) > Delta THEN
Equals := FALSE;
EXIT;
END_IF
END_FOR
// Check for loop bailout
IF NOT Equals THEN
EXIT;
END_IF
END_FOR
// Check for loop bailout
IF NOT Equals THEN
EXIT;
END_IF
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds[1] * SizeOfExpecteds[2] * SizeOfExpecteds[3]),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
ActualsSize := DINT_TO_UDINT(SizeOfActuals[1] * SizeOfActuals[2] * SizeOfActuals[3]),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array3D_REAL,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = [';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(LowerBoundExpecteds[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '..');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(UpperBoundExpecteds[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] (');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := 'x');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := 'x');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ')');
ActualString := 'SIZE = [';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(LowerBoundActuals[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '..');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(UpperBoundActuals[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] (');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := 'x');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := 'x');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ')');
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[1]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[2]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ',');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedArrayIndex[3]));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := REAL_TO_STRING(Expected) );
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[1]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[2]));
ActualString := CONCAT(STR1 := ActualString, STR2 := ',');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualArrayIndex[3]));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := REAL_TO_STRING(Actual));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
Delta
REAL
¶
The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message
T_MaxString
¶
The identifying message for the assertion error
Expecteds
ARRAY[*,*,*] OF REAL
¶
REAL 3d array with expected values
Actuals
ARRAY[*,*,*] OF REAL
¶
REAL 3d array with actual values
AssertArrayEquals_BOOL
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two BOOL arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_BOOL
VAR_IN_OUT
Expecteds : ARRAY[*] OF BOOL; // BOOL array with expected values
Actuals : ARRAY[*] OF BOOL; // BOOL array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_BOOL,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_BOOL,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_BOOL,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := BOOL_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := BOOL_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_BYTE
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two BYTE arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_BYTE
VAR_IN_OUT
Expecteds : ARRAY[*] OF BYTE; // BYTE array with expected values
Actuals : ARRAY[*] OF BYTE; // BYTE array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedByteString : STRING;
ActualByteString : STRING;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_BYTE,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_BYTE,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_BYTE,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedByteString := CONCAT(STR1 := '0x',
STR2 := BYTE_TO_HEXSTR(in := Expecteds[ExpectedsIndex],
iPrecision := 2,
bLoCase := FALSE));
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ExpectedByteString);
ActualByteString := CONCAT(STR1 := '0x',
STR2 := BYTE_TO_HEXSTR(in := Actuals[ActualsIndex],
iPrecision := 2,
bLoCase := FALSE));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := ActualByteString);
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_DINT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two DINT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_DINT
VAR_IN_OUT
Expecteds : ARRAY[*] OF DINT; // DINT array with expected values
Actuals : ARRAY[*] OF DINT; // DINT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_DINT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_DINT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_DINT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_DWORD
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two DWORD arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_DWORD
VAR_IN_OUT
Expecteds : ARRAY[*] OF DWORD; // DWORD array with expected values
Actuals : ARRAY[*] OF DWORD; // DWORD array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedDWordString : STRING;
ActualDWordString : STRING;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_DWORD,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_DWORD,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_DWORD,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedDWordString := CONCAT(STR1 := '0x',
STR2 := DWORD_TO_HEXSTR(in := Expecteds[ExpectedsIndex],
iPrecision := 8,
bLoCase := FALSE));
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ExpectedDWordString);
ActualDWordString := CONCAT(STR1 := '0x',
STR2 := DWORD_TO_HEXSTR(in := Actuals[ActualsIndex],
iPrecision := 8,
bLoCase := FALSE));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := ActualDWordString);
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_INT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two INT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_INT
VAR_IN_OUT
Expecteds : ARRAY[*] OF INT; // INT array with expected values
Actuals : ARRAY[*] OF INT; // INT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_INT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_INT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_INT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := INT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := INT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_LINT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two LINT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_LINT
VAR_IN_OUT
Expecteds : ARRAY[*] OF LINT; // LINT array with expected values
Actuals : ARRAY[*] OF LINT; // LINT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_LINT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_LINT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_LINT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := LINT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := LINT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_LREAL
PUBLIC
¶
Inputs
-
Delta
–The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two LREAL arrays are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_LREAL
VAR_IN_OUT
Expecteds : ARRAY[*] OF LREAL; // LREAL array with expected values
Actuals : ARRAY[*] OF LREAL; // LREAL array with actual values
END_VAR
VAR_INPUT
Delta : LREAL; // The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF ABS(Expecteds[ExpectedsIndex] - Actuals[ActualsIndex]) > Delta THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_LREAL,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := LREAL_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := LREAL_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
Delta
LREAL
¶
The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message
T_MaxString
¶
The identifying message for the assertion error
Expecteds
ARRAY[*] OF LREAL
¶
LREAL array with expected values
Actuals
ARRAY[*] OF LREAL
¶
LREAL array with actual values
AssertArrayEquals_LWORD
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two LWORD arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_LWORD
VAR_IN_OUT
Expecteds : ARRAY[*] OF LWORD; // LWORD array with expected values
Actuals : ARRAY[*] OF LWORD; // LWORD array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedLWordString : STRING;
ActualLWordString : STRING;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_LWORD,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_LWORD,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_LWORD,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedLWordString := CONCAT(STR1 := '0x',
STR2 := LWORD_TO_HEXSTR(in := Expecteds[ExpectedsIndex],
iPrecision := 16,
bLoCase := FALSE));
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ExpectedLWordString);
ActualLWordString := CONCAT(STR1 := '0x',
STR2 := LWORD_TO_HEXSTR(in := Actuals[ActualsIndex],
iPrecision := 16,
bLoCase := FALSE));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := ActualLWordString);
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_REAL
PUBLIC
¶
Inputs
-
Delta
–The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two REAL arrays are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_REAL
VAR_IN_OUT
Expecteds : ARRAY[*] OF REAL; // REAL array with expected values
Actuals : ARRAY[*] OF REAL; // REAL array with actual values
END_VAR
VAR_INPUT
Delta : REAL; // The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF ABS(Expecteds[ExpectedsIndex] - Actuals[ActualsIndex]) > Delta THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_REAL,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := REAL_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := REAL_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
Delta
REAL
¶
The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message
T_MaxString
¶
The identifying message for the assertion error
Expecteds
ARRAY[*] OF REAL
¶
REAL array with expected values
Actuals
ARRAY[*] OF REAL
¶
REAL array with actual values
AssertArrayEquals_SINT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two SINT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_SINT
VAR_IN_OUT
Expecteds : ARRAY[*] OF SINT; // SINT array with expected values
Actuals : ARRAY[*] OF SINT; // SINT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_SINT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_SINT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_SINT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := SINT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := SINT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_UDINT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two UDINT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_UDINT
VAR_IN_OUT
Expecteds : ARRAY[*] OF UDINT; // UDINT array with expected values
Actuals : ARRAY[*] OF UDINT; // UDINT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_UDINT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_UDINT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_UDINT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := UDINT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString :=
CONCAT(STR1 := ActualString, STR2 := UDINT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_UINT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two UINT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_UINT
VAR_IN_OUT
Expecteds : ARRAY[*] OF UINT; // UINT array with expected values
Actuals : ARRAY[*] OF UINT; // UINT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_UINT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_UINT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_UINT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := UINT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := UINT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_ULINT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two ULINT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_ULINT
VAR_IN_OUT
Expecteds : ARRAY[*] OF ULINT; // ULINT array with expected values
Actuals : ARRAY[*] OF ULINT; // ULINT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_ULINT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_ULINT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_ULINT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ULINT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := ULINT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_USINT
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two USINT arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_USINT
VAR_IN_OUT
Expecteds : ARRAY[*] OF USINT; // USINT array with expected values
Actuals : ARRAY[*] OF USINT; // USINT array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_USINT,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_USINT,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_USINT,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := USINT_TO_STRING(Expecteds[ExpectedsIndex]));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := USINT_TO_STRING(Actuals[ActualsIndex]));
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertArrayEquals_WORD
PUBLIC
¶
Inputs
-
Message
–The identifying message for the assertion error
In/Outputs
Source Code
// Asserts that two WORD arrays are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertArrayEquals_WORD
VAR_IN_OUT
Expecteds : ARRAY[*] OF WORD; // WORD array with expected values
Actuals : ARRAY[*] OF WORD; // WORD array with actual values
END_VAR
VAR_INPUT
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Equals : BOOL := TRUE;
SizeEquals : BOOL := TRUE;
Index : DINT;
ExpectedString : T_MaxString;
ActualString : T_MaxString;
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
SizeOfExpecteds : DINT;
SizeOfActuals : DINT;
ExpectedDWordString : STRING;
ActualDWordString : STRING;
ExpectedsIndex : DINT;
ActualsIndex : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
SizeOfExpecteds := ABS(UPPER_BOUND(Expecteds, 1) - LOWER_BOUND(Expecteds, 1)) + 1;
SizeOfActuals := ABS(UPPER_BOUND(Actuals, 1) - LOWER_BOUND(Actuals, 1)) + 1;
IF SizeOfExpecteds <> SizeOfActuals THEN
Equals := FALSE;
SizeEquals := FALSE;
ELSE
(* Even though we know that both arrays are equal in size, the two arrays can start at two completely different
indexes, which needs to be taken into account for. *)
ExpectedsIndex := LOWER_BOUND(Expecteds, 1); // The start position for the expecteds
ActualsIndex := LOWER_BOUND(Actuals, 1); // The start position for the actuals
FOR Index := 1 TO SizeOfExpecteds BY 1 DO
IF Expecteds[ExpectedsIndex] <> Actuals[ActualsIndex] THEN
Equals := FALSE;
EXIT;
END_IF
ExpectedsIndex := ExpectedsIndex + 1;
ActualsIndex := ActualsIndex + 1;
END_FOR
END_IF
AssertArrayResults.ReportResult(ExpectedsSize := DINT_TO_UDINT(SizeOfExpecteds),
ExpectedsTypeClass := IBaseLibrary.TypeClass.TYPE_WORD,
ActualsSize := DINT_TO_UDINT(SizeOfActuals),
ActualsTypeClass := IBaseLibrary.TypeClass.TYPE_WORD,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND NOT Equals THEN
SetTestFailed(AssertionType := E_AssertionType.Type_Array_WORD,
AssertionMessage := Message);
IF NOT SizeEquals THEN
Message := CONCAT(STR1 := Message, STR2 := ', size of arrays not matching.');
ExpectedString := 'SIZE = ';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(SizeOfExpecteds));
ActualString := 'SIZE = ';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(SizeOfActuals));
ELSE
ExpectedDWordString := CONCAT(STR1 := '0x',
STR2 := WORD_TO_HEXSTR(in := Expecteds[ExpectedsIndex],
iPrecision := 4,
bLoCase := FALSE));
ExpectedString := 'ARRAY[';
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := DINT_TO_STRING(ExpectedsIndex));
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := '] = ');
ExpectedString := CONCAT(STR1 := ExpectedString, STR2 := ExpectedDWordString);
ActualDWordString := CONCAT(STR1 := '0x',
STR2 := WORD_TO_HEXSTR(in := Actuals[ActualsIndex],
iPrecision := 4,
bLoCase := FALSE));
ActualString := 'ARRAY[';
ActualString := CONCAT(STR1 := ActualString, STR2 := DINT_TO_STRING(ActualsIndex));
ActualString := CONCAT(STR1 := ActualString, STR2 := '] = ');
ActualString := CONCAT(STR1 := ActualString, STR2 := ActualDWordString);
END_IF
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedString,
Actual := ActualString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals
PUBLIC
¶
Asserts
that two objects (of any type) are equal. If they are not, an assertion error is created. For REAL and LREAL it's recommended to use the AssertEquals_REAL or AssertEquals_LREAL respectively as these give the possibility to specify a delta between the expected and actual value.
Inputs
-
Expected
–Expected value
-
Actual
–The value to check against expected
-
Message
–The identifying message for the assertion error
Source Code
(*
Asserts that two objects (of any type) are equal. If they are not, an assertion error is created.
For REAL and LREAL it's recommended to use the AssertEquals_REAL or AssertEquals_LREAL respectively
as these give the possibility to specify a delta between the expected and actual value.
*)
METHOD PUBLIC AssertEquals
VAR_INPUT
Expected : ANY; // Expected value
Actual : ANY; // The value to check against expected
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
Count : DINT;
ExpectedDataString : T_MaxString;
ActualDataString : T_MaxString;
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
boolExpected : BOOL;
boolActual : BOOL;
byteExpected : BYTE;
byteActual : BYTE;
dateExpected : DATE;
dateActual : DATE;
dateAndTimeExpected : DATE_AND_TIME;
dateAndTimeActual : DATE_AND_TIME;
dintExpected : DINT;
dintActual : DINT;
dwordExpected : DWORD;
dwordActual : DWORD;
intExpected : INT;
intActual : INT;
lintExpected : LINT;
lintActual : LINT;
lrealExpected : LREAL;
lrealActual : LREAL;
ltimeExpected : LTIME;
ltimeActual : LTIME;
lwordExpected : LWORD;
lwordActual : LWORD;
realExpected : REAL;
realActual : REAL;
sintExpected : SINT;
sintActual : SINT;
stringExpected : T_MaxString;
stringActual : T_MaxString;
wstringExpected : WSTRING(255);
wstringActual : WSTRING(255);
timeExpected : TIME;
timeActual : TIME;
timeOfDayExpected : TIME_OF_DAY;
timeOfDayActual : TIME_OF_DAY;
udintExpected : UDINT;
udintActual : UDINT;
uintExpected : UINT;
uintActual : UINT;
ulintExpected : ULINT;
ulintActual : ULINT;
usintExpected : USINT;
usintActual : USINT;
wordExpected : WORD;
wordActual : WORD;
(* ANY comparison variables *)
DataTypesNotEquals : BOOL; // The data type of the two ANY input parameters are not equal
DataSizeNotEquals : BOOL; // The data size of the two ANY input parameters are not equal
DataContentNotEquals : BOOL; // The data content of the two ANY input parameters are not equal
IteratorCounter : DINT;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
(*
This compares two instances of any object type and returns whether they
are the same type, size and value or not. This is necessary for two reasons:
1. So that we can know exactly what differs between the two input parameters
2. It's not possible to do a comparison (= or <>) between two instances of ANY.
*)
// Check whether the type of the inputs differs
IF Expected.TypeClass <> Actual.TypeClass THEN
DataTypesNotEquals := TRUE;
END_IF
// Check whether the size of the inputs differs
IF NOT DataTypesNotEquals THEN
(* Take special care of STRING and WSTRING, as these can be declared with different sizes,
although their content might be the same *)
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_STRING THEN
MEMCPY(destAddr := ADR(stringExpected), srcAddr := Expected.pValue, n := DINT_TO_UDINT(Expected.diSize));
MEMCPY(destAddr := ADR(stringActual), srcAddr := Actual.pValue, n := DINT_TO_UDINT(Actual.diSize));
DataSizeNotEquals := LEN(STR := stringExpected) <> LEN(STR := stringActual);
ELSIF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_WSTRING THEN
MEMCPY(destAddr := ADR(wstringExpected), srcAddr := Expected.pValue, n := DINT_TO_UDINT(Expected.diSize));
MEMCPY(destAddr := ADR(wstringActual), srcAddr := Actual.pValue, n := DINT_TO_UDINT(Actual.diSize));
DataSizeNotEquals := WLEN(STR := wstringExpected) <> WLEN(STR := wstringActual);
ELSIF (Expected.diSize <> Actual.diSize) THEN
DataSizeNotEquals := TRUE;
END_IF
END_IF
// Even though the data type and size are equals, the contents may still differ
IF NOT DataTypesNotEquals AND NOT DataSizeNotEquals THEN
// Compare each byte in the ANY-types
FOR IteratorCounter := 0 TO Expected.diSize - 1 BY 1 DO
IF Expected.pValue[IteratorCounter] <> Actual.pValue[IteratorCounter] THEN
DataContentNotEquals := TRUE;
EXIT;
END_IF
END_FOR
END_IF
(* First check whether the input data are any of the standard data types that are supported by TcUnit.
In this case call the standard Assert-methods for that data. But before doing that we need to make sure
that both the expected and actual:
- Have both the same data type
- Both have the same data size
*)
IF NOT DataTypesNotEquals AND NOT DataSizeNotEquals THEN
// BOOL
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_BOOL THEN
MEMCPY(destAddr := ADR(boolExpected), srcAddr := Expected.pValue, n := SIZEOF(BOOL));
MEMCPY(destAddr := ADR(boolActual), srcAddr := Actual.pValue, n := SIZEOF(BOOL));
AssertEquals_BOOL(Expected := boolExpected, Actual := boolActual, Message := Message);
RETURN;
END_IF
// BYTE
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_BYTE THEN
MEMCPY(destAddr := ADR(byteExpected), srcAddr := Expected.pValue, n := SIZEOF(BYTE));
MEMCPY(destAddr := ADR(byteActual), srcAddr := Actual.pValue, n := SIZEOF(BYTE));
AssertEquals_BYTE(Expected := byteExpected, Actual := byteActual, Message := Message);
RETURN;
END_IF
// DATE
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_DATE THEN
MEMCPY(destAddr := ADR(dateExpected), srcAddr := Expected.pValue, n := SIZEOF(DATE));
MEMCPY(destAddr := ADR(dateActual), srcAddr := Actual.pValue, n := SIZEOF(DATE));
AssertEquals_DATE(Expected := dateExpected, Actual := dateActual, Message := Message);
RETURN;
END_IF
// DATE_AND_TIME
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_DATEANDTIME THEN
MEMCPY(destAddr := ADR(dateAndTimeExpected), srcAddr := Expected.pValue, n := SIZEOF(DATE_AND_TIME));
MEMCPY(destAddr := ADR(dateAndTimeActual), srcAddr := Actual.pValue, n := SIZEOF(DATE_AND_TIME));
AssertEquals_DATE_AND_TIME(Expected := dateAndTimeExpected, Actual := dateAndTimeActual, Message := Message);
RETURN;
END_IF
// DINT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_DINT THEN
MEMCPY(destAddr := ADR(dintExpected), srcAddr := Expected.pValue, n := SIZEOF(DINT));
MEMCPY(destAddr := ADR(dintActual), srcAddr := Actual.pValue, n := SIZEOF(DINT));
AssertEquals_DINT(Expected := dintExpected, Actual := dintActual, Message := Message);
RETURN;
END_IF
// DWORD
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_DWORD THEN
MEMCPY(destAddr := ADR(dwordExpected), srcAddr := Expected.pValue, n := SIZEOF(DWORD));
MEMCPY(destAddr := ADR(dwordActual), srcAddr := Actual.pValue, n := SIZEOF(DWORD));
AssertEquals_DWORD(Expected := dwordExpected, Actual := dwordActual, Message := Message);
RETURN;
END_IF
// INT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_INT THEN
MEMCPY(destAddr := ADR(intExpected), srcAddr := Expected.pValue, n := SIZEOF(INT));
MEMCPY(destAddr := ADR(intActual), srcAddr := Actual.pValue, n := SIZEOF(INT));
AssertEquals_INT(Expected := intExpected, Actual := intActual, Message := Message);
RETURN;
END_IF
// LINT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_LINT THEN
MEMCPY(destAddr := ADR(lintExpected), srcAddr := Expected.pValue, n := SIZEOF(LINT));
MEMCPY(destAddr := ADR(lintActual), srcAddr := Actual.pValue, n := SIZEOF(LINT));
AssertEquals_LINT(Expected := lintExpected, Actual := lintActual, Message := Message);
RETURN;
END_IF
// LREAL
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_LREAL THEN
MEMCPY(destAddr := ADR(lrealExpected), srcAddr := Expected.pValue, n := SIZEOF(LREAL));
MEMCPY(destAddr := ADR(lrealActual), srcAddr := Actual.pValue, n := SIZEOF(LREAL));
AssertEquals_LREAL(Expected := lrealExpected, Actual := lrealActual, Delta := 0.0, Message := Message);
RETURN;
END_IF
// LTIME
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_LTIME THEN
MEMCPY(destAddr := ADR(ltimeExpected), srcAddr := Expected.pValue, n := SIZEOF(LTIME));
MEMCPY(destAddr := ADR(ltimeActual), srcAddr := Actual.pValue, n := SIZEOF(LTIME));
AssertEquals_LTIME(Expected := ltimeExpected, Actual := ltimeActual, Message := Message);
RETURN;
END_IF
// LWORD
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_LWORD THEN
MEMCPY(destAddr := ADR(lwordExpected), srcAddr := Expected.pValue, n := SIZEOF(LWORD));
MEMCPY(destAddr := ADR(lwordActual), srcAddr := Actual.pValue, n := SIZEOF(LWORD));
AssertEquals_LWORD(Expected := lwordExpected, Actual := lwordActual, Message := Message);
RETURN;
END_IF
// REAL
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_REAL THEN
MEMCPY(destAddr := ADR(realExpected), srcAddr := Expected.pValue, n := SIZEOF(REAL));
MEMCPY(destAddr := ADR(realActual), srcAddr := Actual.pValue, n := SIZEOF(REAL));
AssertEquals_REAL(Expected := realExpected, Actual := realActual, Delta := 0.0, Message := Message);
RETURN;
END_IF
// SINT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_SINT THEN
MEMCPY(destAddr := ADR(sintExpected), srcAddr := Expected.pValue, n := SIZEOF(SINT));
MEMCPY(destAddr := ADR(sintActual), srcAddr := Actual.pValue, n := SIZEOF(SINT));
AssertEquals_SINT(Expected := sintExpected, Actual := sintActual, Message := Message);
RETURN;
END_IF
// STRING
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_STRING THEN
MEMCPY(destAddr := ADR(stringExpected), srcAddr := Expected.pValue, n := DINT_TO_UDINT(Expected.diSize));
MEMCPY(destAddr := ADR(stringActual), srcAddr := Actual.pValue, n := DINT_TO_UDINT(Actual.diSize));
AssertEquals_STRING(Expected := stringExpected, Actual := stringActual, Message := Message);
RETURN;
END_IF
// WSTRING
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_WSTRING THEN
MEMCPY(destAddr := ADR(wstringExpected), srcAddr := Expected.pValue, n := DINT_TO_UDINT(Expected.diSize));
MEMCPY(destAddr := ADR(wstringActual), srcAddr := Actual.pValue, n := DINT_TO_UDINT(Actual.diSize));
AssertEquals_WSTRING(Expected := wstringExpected, Actual := wstringActual, Message := Message);
RETURN;
END_IF
// TIME
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_TIME THEN
MEMCPY(destAddr := ADR(timeExpected), srcAddr := Expected.pValue, n := SIZEOF(TIME));
MEMCPY(destAddr := ADR(timeActual), srcAddr := Actual.pValue, n := SIZEOF(TIME));
AssertEquals_TIME(Expected := timeExpected, Actual := timeActual, Message := Message);
RETURN;
END_IF
// TIME_OF_DAY
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_TIMEOFDAY THEN
MEMCPY(destAddr := ADR(timeOfDayExpected), srcAddr := Expected.pValue, n := SIZEOF(TIME_OF_DAY));
MEMCPY(destAddr := ADR(timeOfDayActual), srcAddr := Actual.pValue, n := SIZEOF(TIME_OF_DAY));
AssertEquals_TIME_OF_DAY(Expected := timeOfDayExpected, Actual := timeOfDayActual, Message := Message);
RETURN;
END_IF
// UDINT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_UDINT THEN
MEMCPY(destAddr := ADR(udintExpected), srcAddr := Expected.pValue, n := SIZEOF(UDINT));
MEMCPY(destAddr := ADR(udintActual), srcAddr := Actual.pValue, n := SIZEOF(UDINT));
AssertEquals_UDINT(Expected := udintExpected, Actual := udintActual, Message := Message);
RETURN;
END_IF
// UINT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_UINT THEN
MEMCPY(destAddr := ADR(uintExpected), srcAddr := Expected.pValue, n := SIZEOF(UINT));
MEMCPY(destAddr := ADR(uintActual), srcAddr := Actual.pValue, n := SIZEOF(UINT));
AssertEquals_UINT(Expected := uintExpected, Actual := uintActual, Message := Message);
RETURN;
END_IF
// ULINT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_ULINT THEN
MEMCPY(destAddr := ADR(ulintExpected), srcAddr := Expected.pValue, n := SIZEOF(ULINT));
MEMCPY(destAddr := ADR(ulintActual), srcAddr := Actual.pValue, n := SIZEOF(ULINT));
AssertEquals_ULINT(Expected := ulintExpected, Actual := ulintActual, Message := Message);
RETURN;
END_IF
// USINT
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_USINT THEN
MEMCPY(destAddr := ADR(usintExpected), srcAddr := Expected.pValue, n := SIZEOF(USINT));
MEMCPY(destAddr := ADR(usintActual), srcAddr := Actual.pValue, n := SIZEOF(USINT));
AssertEquals_USINT(Expected := usintExpected, Actual := usintActual, Message := Message);
RETURN;
END_IF
// WORD
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_WORD THEN
MEMCPY(destAddr := ADR(wordExpected), srcAddr := Expected.pValue, n := SIZEOF(WORD));
MEMCPY(destAddr := ADR(wordActual), srcAddr := Actual.pValue, n := SIZEOF(WORD));
AssertEquals_WORD(Expected := wordExpected, Actual := wordActual, Message := Message);
RETURN;
END_IF
END_IF
(* If we've come to this row, it means that the data input is not any of the standard primitive data types, and thus
we need to do special handling *)
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
IF DataTypesNotEquals THEN
ExpectedDataString := CONCAT(STR1 := '(Type class = ', STR2 := F_AnyTypeClassToString((Expected.TypeClass)));
ExpectedDataString := CONCAT(STR1 := ExpectedDataString, STR2 := ')');
ActualDataString := CONCAT(STR1 := '(Type class = ', STR2 := F_AnyTypeClassToString(Actual.TypeClass));
ActualDataString := CONCAT(STR1 := ActualDataString, STR2 := ')');
ELSIF DataSizeNotEquals THEN
(* Take special care of STRING and WSTRING, as these can be declared with different sizes,
although their content might be the same *)
IF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_STRING THEN
MEMCPY(destAddr := ADR(stringExpected), srcAddr := Expected.pValue, n := DINT_TO_UDINT(Expected.diSize));
MEMCPY(destAddr := ADR(stringActual), srcAddr := Actual.pValue, n := DINT_TO_UDINT(Actual.diSize));
ExpectedDataString := CONCAT(STR1 := '(Data size (LEN) = ', STR2 := INT_TO_STRING(LEN(STR := stringExpected)));
ActualDataString := CONCAT(STR1 := '(Data size (LEN) = ', STR2 := INT_TO_STRING(LEN(STR := stringActual)));
ELSIF UDINT_TO_INT(Expected.TypeClass) = IBaseLibrary.TypeClass.TYPE_WSTRING THEN
MEMCPY(destAddr := ADR(wstringExpected), srcAddr := Expected.pValue, n := DINT_TO_UDINT(Expected.diSize));
MEMCPY(destAddr := ADR(wstringActual), srcAddr := Actual.pValue, n := DINT_TO_UDINT(Actual.diSize));
ExpectedDataString := CONCAT(STR1 := '(Data size (WLEN) = ', STR2 := INT_TO_STRING(WLEN(STR := wstringExpected)));
ActualDataString := CONCAT(STR1 := '(Data size (WLEN) = ', STR2 := INT_TO_STRING(WLEN(STR := wstringActual)));
ELSE
ExpectedDataString := CONCAT(STR1 := '(Data size = ', STR2 := DINT_TO_STRING(Expected.diSize));
ActualDataString := CONCAT(STR1 := '(Data size = ', STR2 := DINT_TO_STRING(Actual.diSize));
END_IF
ExpectedDataString := CONCAT(STR1 := ExpectedDataString, STR2 := ')');
ActualDataString := CONCAT(STR1 := ActualDataString, STR2 := ')');
ELSIF DataContentNotEquals THEN
FOR Count := 0 TO MIN(Expected.diSize-1, 38) BY 1 DO // One byte will equal two characters (example: 255 = 0xff, 1 = 0x01)
ExpectedDataString := CONCAT(STR1 := ExpectedDataString,
STR2 := BYTE_TO_HEXSTR(in := Expected.pValue[Count],
iPrecision := 2,
bLoCase := FALSE));
END_FOR
ExpectedDataString := CONCAT(STR1 := '0x', STR2 := ExpectedDataString);
FOR Count := 0 TO MIN(Actual.diSize-1, 38) BY 1 DO // One byte will equal two characters (example: 255 = 0xff, 1 = 0x01)
ActualDataString := CONCAT(STR1 := ActualDataString,
STR2 := BYTE_TO_HEXSTR(in := Actual.pValue[Count],
iPrecision := 2,
bLoCase := FALSE));
END_FOR
ActualDataString := CONCAT(STR1 := '0x', STR2 := ActualDataString);
END_IF
AssertResults.ReportResult(ExpectedSize := DINT_TO_UDINT(Expected.diSize),
ExpectedTypeClass := UDINT_TO_INT(Expected.TypeClass),
ExpectedValue := Expected.pValue,
ActualSize := DINT_TO_UDINT(Actual.diSize),
ActualTypeClass := UDINT_TO_INT(Actual.TypeClass),
ActualValue := Actual.pValue,
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND (DataTypesNotEquals OR DataSizeNotEquals OR DataContentNotEquals) THEN
SetTestFailed(AssertionType := E_AssertionType.Type_ANY,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := ExpectedDataString,
Actual := ActualDataString,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_BOOL
PUBLIC
¶
Inputs
-
Expected
–BOOL expected value
-
Actual
–BOOL actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two BOOLs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_BOOL
VAR_INPUT
Expected : BOOL; // BOOL expected value
Actual : BOOL; // BOOL actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_BOOL,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_BOOL,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_BOOL,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := BOOL_TO_STRING(Expected),
Actual := BOOL_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_BYTE
PUBLIC
¶
Inputs
-
Expected
–BYTE expected value
-
Actual
–BYTE actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two BYTEs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_BYTE
VAR_INPUT
Expected : BYTE; // BYTE expected value
Actual : BYTE; // BYTE actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_BYTE,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_BYTE,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_BYTE,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := CONCAT(
STR1 := '0x',
STR2 := BYTE_TO_HEXSTR(in := Expected,
iPrecision := 2,
bLoCase := FALSE)),
Actual := CONCAT(
STR1 := '0x',
STR2 := BYTE_TO_HEXSTR(in := Actual,
iPrecision := 2,
bLoCase := FALSE)),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_DATE
PUBLIC
¶
Inputs
-
Expected
–DATE expected value
-
Actual
–DATE actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two DATEs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_DATE
VAR_INPUT
Expected : DATE; // DATE expected value
Actual : DATE; // DATE actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_DATE,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_DATE,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_DATE,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := DATE_TO_STRING(Expected),
Actual := DATE_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_DATE_AND_TIME
PUBLIC
¶
Inputs
-
Expected
–DATE_AND_TIME expected value
-
Actual
–DATE_AND_TIME actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two DATE_AND_TIMEs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_DATE_AND_TIME
VAR_INPUT
Expected : DATE_AND_TIME; // DATE_AND_TIME expected value
Actual : DATE_AND_TIME; // DATE_AND_TIME actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_DATEANDTIME,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_DATEANDTIME,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_DATE_AND_TIME,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := DT_TO_STRING(Expected),
Actual := DT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_DINT
PUBLIC
¶
Inputs
-
Expected
–DINT expected value
-
Actual
–DINT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two DINTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_DINT
VAR_INPUT
Expected : DINT; // DINT expected value
Actual : DINT; // DINT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_DINT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_DINT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_DINT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := DINT_TO_STRING(Expected),
Actual := DINT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_DWORD
PUBLIC
¶
Inputs
-
Expected
–DWORD expected value
-
Actual
–DWORD actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two DWORDs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_DWORD
VAR_INPUT
Expected : DWORD; // DWORD expected value
Actual : DWORD; // DWORD actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_DWORD,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_DWORD,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_DWORD,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := CONCAT(
STR1 := '0x',
STR2 := DWORD_TO_HEXSTR(in := Expected,
iPrecision := 8,
bLoCase := FALSE)),
Actual := CONCAT(
STR1 := '0x',
STR2 := DWORD_TO_HEXSTR(in := Actual,
iPrecision := 8,
bLoCase := FALSE)),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_INT
PUBLIC
¶
Inputs
-
Expected
–INT expected value
-
Actual
–INT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two INTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_INT
VAR_INPUT
Expected : INT; // INT expected value
Actual : INT; // INT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_INT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_INT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_INT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := INT_TO_STRING(Expected),
Actual := INT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_LINT
PUBLIC
¶
Inputs
-
Expected
–LINT expected value
-
Actual
–LINT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two LINTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_LINT
VAR_INPUT
Expected : LINT; // LINT expected value
Actual : LINT; // LINT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_LINT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_LINT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_LINT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := LINT_TO_STRING(Expected),
Actual := LINT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_LREAL
PUBLIC
¶
Inputs
-
Expected
–LREAL expected value
-
Actual
–LREAL actual value
-
Delta
–The maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two LREALs are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_LREAL
VAR_INPUT
Expected : LREAL; // LREAL expected value
Actual : LREAL; // LREAL actual value
Delta : LREAL; // The maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_LREAL,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND ABS(Expected - Actual) > Delta THEN
SetTestFailed(AssertionType := E_AssertionType.Type_LREAL,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := LREAL_TO_STRING(Expected),
Actual := LREAL_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_LTIME
PUBLIC
¶
Inputs
-
Expected
–LTIME expected value
-
Actual
–LTIME actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two LTIMEs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_LTIME
VAR_INPUT
Expected : LTIME; // LTIME expected value
Actual : LTIME; // LTIME actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_LTIME,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_LTIME,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_LTIME,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := LTIME_TO_STRING(Expected),
Actual := LTIME_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_LWORD
PUBLIC
¶
Inputs
-
Expected
–LWORD expected value
-
Actual
–LWORD actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two LWORDs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_LWORD
VAR_INPUT
Expected : LWORD; // LWORD expected value
Actual : LWORD; // LWORD actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_LWORD,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_LWORD,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_LWORD,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := CONCAT(
STR1 := '0x',
STR2 := LWORD_TO_HEXSTR(in := Expected,
iPrecision := 16,
bLoCase := FALSE)),
Actual := CONCAT(
STR1 := '0x',
STR2 := LWORD_TO_HEXSTR(in := Actual,
iPrecision := 16,
bLoCase := FALSE)),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_REAL
PUBLIC
¶
Inputs
-
Expected
–REAL expected value
-
Actual
–REAL actual value
-
Delta
–The maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two REALs are equal to within a positive delta. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_REAL
VAR_INPUT
Expected : REAL; // REAL expected value
Actual : REAL; // REAL actual value
Delta : REAL; // The maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_REAL,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND ABS(Expected - Actual) > Delta THEN
SetTestFailed(AssertionType := E_AssertionType.Type_REAL,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := REAL_TO_STRING(Expected),
Actual := REAL_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_SINT
PUBLIC
¶
Inputs
-
Expected
–SINT expected value
-
Actual
–SINT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two SINTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_SINT
VAR_INPUT
Expected : SINT; // SINT expected value
Actual : SINT; // SINT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_SINT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_SINT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_SINT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := SINT_TO_STRING(Expected),
Actual := SINT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_STRING
PUBLIC
¶
Inputs
-
Expected
–STRING expected value
-
Actual
–STRING actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two STRINGs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_STRING
VAR_INPUT
Expected : T_MaxString; // STRING expected value
Actual : T_MaxString; // STRING actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_STRING,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_STRING,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND (LEN(STR := Expected) <> LEN(STR := Actual) OR (Expected <> Actual)) THEN
SetTestFailed(AssertionType := E_AssertionType.Type_STRING,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := Expected,
Actual := Actual,
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_TIME
PUBLIC
¶
Inputs
-
Expected
–TIME expected value
-
Actual
–TIME actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two TIMEs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_TIME
VAR_INPUT
Expected : TIME; // TIME expected value
Actual : TIME; // TIME actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_TIME,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_TIME,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_TIME,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := TIME_TO_STRING(Expected),
Actual := TIME_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_TIME_OF_DAY
PUBLIC
¶
Inputs
-
Expected
–TIME_OF_DAY expected value
-
Actual
–TIME_OF_DAY actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two TIME_OF_DAYs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_TIME_OF_DAY
VAR_INPUT
Expected : TIME_OF_DAY; // TIME_OF_DAY expected value
Actual : TIME_OF_DAY; // TIME_OF_DAY actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_TIMEOFDAY,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_TIMEOFDAY,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_TIME_OF_DAY,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := TOD_TO_STRING(Expected),
Actual := TOD_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_UDINT
PUBLIC
¶
Inputs
-
Expected
–UDINT expected value
-
Actual
–UDINT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two UDINTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_UDINT
VAR_INPUT
Expected : UDINT; // UDINT expected value
Actual : UDINT; // UDINT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_UDINT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_UDINT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_UDINT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := UDINT_TO_STRING(Expected),
Actual := UDINT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_UINT
PUBLIC
¶
Inputs
-
Expected
–UINT expected value
-
Actual
–UINT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two UINTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_UINT
VAR_INPUT
Expected : UINT; // UINT expected value
Actual : UINT; // UINT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_UINT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_UINT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_UINT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := UINT_TO_STRING(Expected),
Actual := UINT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_ULINT
PUBLIC
¶
Inputs
-
Expected
–ULINT expected value
-
Actual
–ULINT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two ULINTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_ULINT
VAR_INPUT
Expected : ULINT; // ULINT expected value
Actual : ULINT; // ULINT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_ULINT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_ULINT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_ULINT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := ULINT_TO_STRING(Expected),
Actual := ULINT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_USINT
PUBLIC
¶
Inputs
-
Expected
–USINT expected value
-
Actual
–USINT actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two USINTs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_USINT
VAR_INPUT
Expected : USINT; // USINT expected value
Actual : USINT; // USINT actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
AlreadyReported : BOOL;
TestInstancePath : T_MaxString;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_USINT,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_USINT,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_USINT,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := USINT_TO_STRING(Expected),
Actual := USINT_TO_STRING(Actual),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_WORD
PUBLIC
¶
Inputs
-
Expected
–WORD expected value
-
Actual
–WORD actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two WORDs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_WORD
VAR_INPUT
Expected : WORD; // WORD expected value
Actual : WORD; // WORD actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_WORD,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_WORD,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND Expected <> Actual THEN
SetTestFailed(AssertionType := E_AssertionType.Type_WORD,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := CONCAT(
STR1 := '0x',
STR2 := WORD_TO_HEXSTR(in := Expected,
iPrecision := 4,
bLoCase := FALSE)),
Actual := CONCAT(
STR1 := '0x',
STR2 := WORD_TO_HEXSTR(in := Actual,
iPrecision := 4,
bLoCase := FALSE)),
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertEquals_WSTRING
PUBLIC
¶
Inputs
-
Expected
–WSTRING expected value
-
Actual
–WSTRING actual value
-
Message
–The identifying message for the assertion error
Source Code
// Asserts that two WSTRINGs are equal. If they are not, an assertion error is created.
METHOD PUBLIC AssertEquals_WSTRING
VAR_INPUT
Expected : WSTRING(255); // WSTRING expected value
Actual : WSTRING(255); // WSTRING actual value
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
VAR
TestInstancePath : T_MaxString;
AlreadyReported : BOOL;
END_VAR
IF GVL_TcUnit.IgnoreCurrentTest OR GVL_TcUnit.CurrentTestIsFinished THEN
RETURN;
END_IF
TestInstancePath := AddTestNameToInstancePath(TestInstancePath := FindTestSuiteInstancePath());
AssertResults.ReportResult(ExpectedSize := SIZEOF(Expected),
ExpectedTypeClass := IBaseLibrary.TypeClass.TYPE_WSTRING,
ExpectedValue := ADR(Expected),
ActualSize := SIZEOF(Actual),
ActualTypeClass := IBaseLibrary.TypeClass.TYPE_WSTRING,
ActualValue := ADR(Actual),
Message := Message,
TestInstancePath := TestInstancePath,
AlreadyReported => AlreadyReported);
IF NOT AlreadyReported AND (WLEN(STR := Expected) <> WLEN(STR := Actual) OR (Expected <> Actual)) THEN
SetTestFailed(AssertionType := E_AssertionType.Type_WSTRING,
AssertionMessage := Message);
AssertMessageFormatter.LogAssertFailure(Expected := 'Not possible to print EXP unicode WSTRING value',
Actual := 'Not possible to print ACT unicode WSTRING value',
Message := Message,
TestInstancePath := TestInstancePath);
END_IF
AssertFalse
PUBLIC
¶
Inputs
Source Code
// Asserts that a condition is false. If it is not, an assertion error is created.
METHOD PUBLIC AssertFalse
VAR_INPUT
Condition : BOOL; // Condition to be checked
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
AssertEquals_BOOL(Expected := FALSE,
Actual := Condition,
Message := Message);
AssertTrue
PUBLIC
¶
Inputs
Source Code
// Asserts that a condition is true. If it is not, an assertion error is created.
METHOD PUBLIC AssertTrue
VAR_INPUT
Condition : BOOL; // Condition to be checked
Message : T_MaxString; // The identifying message for the assertion error
END_VAR
AssertEquals_BOOL(Expected := TRUE,
Actual := Condition,
Message := Message);
CalculateAndSetNumberOfAssertsForTest
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL CalculateAndSetNumberOfAssertsForTest
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
TestInstancePath : T_MaxString;
TotalNumberOfAsserts : UINT;
NumberOfAsserts : UINT;
NumberOfArrayAsserts : UINT;
IteratorCounter : UINT;
END_VAR
TestInstancePath := AddTestNameToInstancePath(FindTestSuiteInstancePath());
NumberOfAsserts := AssertResults.GetNumberOfAssertsForTest(CompleteTestInstancePath := TestInstancePath);
NumberOfArrayAsserts := AssertArrayResults.GetNumberOfArrayAssertsForTest(CompleteTestInstancePath := TestInstancePath);
TotalNumberOfAsserts := NumberOfAsserts + NumberOfArrayAsserts;
IF TotalNumberOfAsserts > 0 THEN
IF NumberOfTests > 0 THEN
FOR IteratorCounter := 1 TO NumberOfTests BY 1 DO
IF Tests[IteratorCounter].GetName() = TestName THEN
Tests[IteratorCounter].SetNumberOfAssertions(NoOfAssertions := TotalNumberOfAsserts);
RETURN;
END_IF
END_FOR
END_IF
END_IF
TestName
T_MaxString
¶
CalculateDuration
INTERNAL
¶
Inputs
-
FinishedAt
–CPU cycle counter with 100ns precision
Source Code
METHOD INTERNAL CalculateDuration
VAR_INPUT
FinishedAt : LWORD; // CPU cycle counter with 100ns precision
END_VAR
IF Duration = 0.0 THEN
Duration := LWORD_TO_LREAL(FinishedAt - StartedAt) * GVL_TcUnit.HundredNanosecondToSecond; // Seconds
END_IF
FinishedAt
LWORD
¶
CPU cycle counter with 100ns precision
FB_init
BOOL
¶
Inputs
-
bInitRetains
–if TRUE, the retain variables are initialized (warm start / cold start)
-
bInCopyCode
–if TRUE, the instance afterwards gets moved into the copy code (online change)
Source Code
METHOD FB_init : BOOL
VAR_INPUT
bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
END_VAR
GVL_TcUnit.NumberOfInitializedTestSuites := GVL_TcUnit.NumberOfInitializedTestSuites + 1;
GVL_TcUnit.TestSuiteAddresses[GVL_TcUnit.NumberOfInitializedTestSuites] := THIS;
FindTestSuiteInstancePath
PRIVATE
¶
Source Code
// Searches for the instance path of the calling function block
METHOD PRIVATE FindTestSuiteInstancePath : T_MaxString
FindTestSuiteInstancePath := GetInstancePath();
GetDuration
INTERNAL
¶
Source Code
METHOD INTERNAL GetDuration : LREAL
GetDuration := Duration;
GetHasStartedRunning
INTERNAL
¶
Source Code
METHOD INTERNAL GetHasStartedRunning : BOOL
GetHasStartedRunning := StartedAt > 0;
GetInstancePath
INTERNAL
¶
Source Code
METHOD INTERNAL GetInstancePath : T_MaxString
GetInstancePath := InstancePath;
GetNumberOfFailedTests
INTERNAL
¶
Source Code
METHOD INTERNAL GetNumberOfFailedTests : UINT
VAR
Counter : UINT;
FailedTestsCount : UINT;
NumberOfTestsToAnalyse : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
NumberOfTestOverArrayLimit : UINT;
END_VAR
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
IF GetNumberOfTests() > NumberOfTestsToAnalyse THEN
NumberOfTestOverArrayLimit := GetNumberOfTests()-NumberOfTestsToAnalyse;
END_IF
FOR Counter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[Counter].IsFailed() THEN
FailedTestsCount := FailedTestsCount + 1;
END_IF
END_FOR
GetNumberOfFailedTests := FailedTestsCount + NumberOfTestOverArrayLimit;
GetNumberOfSkippedTests
INTERNAL
¶
Source Code
METHOD INTERNAL GetNumberOfSkippedTests : UINT
VAR
Counter : UINT;
SkippedTestsCount : UINT;
NumberOfTestsToAnalyse : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
FOR Counter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[Counter].IsSkipped() THEN
SkippedTestsCount := SkippedTestsCount + 1;
END_IF
END_FOR
GetNumberOfSkippedTests := SkippedTestsCount;
GetNumberOfSuccessfulTests
INTERNAL
¶
Source Code
METHOD INTERNAL GetNumberOfSuccessfulTests : UINT
GetNumberOfSuccessfulTests := GetNumberOfTests() - GetNumberOfFailedTests() - GetNumberOfSkippedTests();
GetNumberOfTests
INTERNAL
¶
Source Code
METHOD INTERNAL GetNumberOfTests : UINT
GetNumberOfTests := NumberOfTests;
GetNumberOfTestsToAnalyse
INTERNAL
¶
Source Code
METHOD INTERNAL GetNumberOfTestsToAnalyse : UINT
GetNumberOfTestsToAnalyse := MIN(GetNumberOfTests(), GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
GetTestByName
REFERENCE TO FB_Test
¶
Inputs
Source Code
METHOD GetTestByName : REFERENCE TO FB_Test
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
NumberOfTestsToAnalyse : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestSuites);
END_VAR
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[IteratorCounter].GetName() = TestName THEN
GetTestByName REF= Tests[IteratorCounter];
RETURN;
END_IF
END_FOR
TestName
T_MaxString
¶
GetTestByPosition
INTERNAL
¶
Inputs
Source Code
// This method returns the test at the n'th position, ranging from 1.. NumberOfTests
METHOD INTERNAL GetTestByPosition : FB_Test
VAR_INPUT
Position : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
GetTestByPosition := Tests[Position];
Position
UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)
¶
GetTestOrderNumber
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL GetTestOrderNumber : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
NumberOfTestsToAnalyse : UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[IteratorCounter].GetName() = TestName THEN
GetTestOrderNumber := Tests[IteratorCounter].GetTestOrder();
RETURN;
END_IF
END_FOR
TestName
T_MaxString
¶
IsTestFinished
INTERNAL
¶
Inputs
Source Code
METHOD INTERNAL IsTestFinished : BOOL
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
NumberOfTestsToAnalyse : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
IsTestFinished := FALSE;
FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[IteratorCounter].GetName() = TestName THEN
IsTestFinished := Tests[IteratorCounter].IsFinished();
RETURN;
END_IF
END_FOR
TestName
T_MaxString
¶
SetStartedAtIfNotSet
INTERNAL
¶
SetStartedAtTimeBasedOnCpuCounter
INTERNAL
¶
Source Code
METHOD INTERNAL SetStartedAtTimeBasedOnCpuCounter
StartedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter);
SetTestFailed
PRIVATE
¶
Inputs
Source Code
METHOD PRIVATE SetTestFailed
VAR_INPUT
AssertionType : E_AssertionType;
AssertionMessage : T_MaxString;
END_VAR
VAR
IteratorCounter : UINT;
NumberOfTestsToAnalyse : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[IteratorCounter].GetName() = GVL_TcUnit.CurrentTestNameBeingCalled THEN
Tests[IteratorCounter].SetFailed();
Tests[IteratorCounter].SetAssertionType(AssertType := AssertionType);
Tests[IteratorCounter].SetAssertionMessage(AssertMessage := AssertionMessage);
END_IF
END_FOR
SetTestFinished
INTERNAL
¶
Inputs
Source Code
(* Marks the test as finished in this testsuite.
Returns TRUE if test was found, and FALSE if a test with this name was not found in this testsuite *)
METHOD INTERNAL SetTestFinished : BOOL;
VAR_INPUT
TestName : T_MaxString;
FinishedAt : LWORD;
END_VAR
VAR
IteratorCounter : UINT;
NumberOfTestsToAnalyse : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
END_VAR
// Limit the test analyse to the max array limit of 'Tests[]'
NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse();
FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO
IF Tests[IteratorCounter].GetName() = TestName THEN
IF NOT Tests[IteratorCounter].IsFinished() THEN
Tests[IteratorCounter].SetFinishedAndDuration(FinishedAt := FinishedAt);
END_IF
SetTestFinished := TRUE;
RETURN;
END_IF
END_FOR
SetTestFinished := FALSE;
FB_XmlControl
¶
Organizes
parsing and composing of XML data. Data can be treated as STRING or char array. Buffer size of file can be set via GVL_Param_TcUnit (xUnitBufferSize)
Methods
-
ClearBuffer
-
CloseTag
-
NewComment
-
NewParameter
-
NewTag
-
NewTagData
-
SetBuffer
-
ToStartBuffer
-
WriteDocumentHeader
Properties
Source Code
(*
Organizes parsing and composing of XML data. Data can be treated as STRING or char array.
Buffer size of file can be set via GVL_Param_TcUnit (xUnitBufferSize)
*)
FUNCTION_BLOCK FB_XmlControl
VAR
XmlBuffer : FB_StreamBuffer;
TagListBuffer : FB_StreamBuffer;
Tags : T_MaxString;
TagListSeekBuffer : FB_StreamBuffer;
TagsSeek : STRING;
TagBuffer : FB_StreamBuffer;
Tag : T_MaxString;
TagOpen: BOOL;
Select : UDINT;
SearchPosition : UDINT;
END_VAR
VAR CONSTANT
TAG_OPEN : STRING(1) := '<';
TAG_CLOSE : STRING(1) := '>';
END_TAG_CLOSE : STRING(2) := '/>';
SPACE : STRING(1) := ' ';
EQUALS : STRING(1) := '=';
QUOTE : STRING(1) := '"';
BACK_SLASH : STRING(1) := '\';
FORWARD_SLASH : STRING(1) := '/';
OPEN_COMMENT : STRING(5) := '<!-- ';
CLOSE_COMMENT : STRING(4) := ' -->';
TAB : STRING(2) := '$T';
CR_LF : STRING(4) := '$R$N';
// $OD : ASCII code for carriage return (CR)
// $$ : to add a $R
// $' : to add ' (apostrophe)
// $L or $l : line feed
// $N or $n : new line
// $P or $p : next page
// $R or $r : end of line
END_VAR
ClearBuffer
PUBLIC
¶
Source Code
// Clears the contents of the entire buffer.
METHOD PUBLIC ClearBuffer
SearchPosition := 0;
TagListSeekBuffer.Length := 0;
XmlBuffer.Length := 0;
TagsSeek := '';
Tag := '';
CloseTag
PUBLIC
¶
Closes
a Tag:
XML:
Method: XML.CloseTag();
Source Code
(*
Closes a Tag:
XML: <MyTag />'
Method: XML.CloseTag();
*)
METHOD PUBLIC CloseTag : T_MaxString
VAR
ClosedTag : T_MaxString;
END_VAR
IF TagOpen THEN
XmlBuffer.Append := END_TAG_CLOSE;
Select := TagListBuffer.FindBack(SearchString := FORWARD_SLASH);
ClosedTag := TagListBuffer.CutOff(StartPos := Select);
TagOpen := FALSE;
ELSE
Select := TagListBuffer.FindBack(SearchString := FORWARD_SLASH);
ClosedTag := TagListBuffer.CutOff(StartPos := Select);
XmlBuffer.Append := TAG_OPEN;
XmlBuffer.Append := ClosedTag;
XmlBuffer.Append := TAG_CLOSE;
END_IF
CloseTag := ClosedTag;
NewComment
PUBLIC
¶
Adds
a comment XML:
XML.NewComment(Comment: = 'MyComment');
Inputs
Source Code
(*
Adds a comment
XML: <!-- MyComment -->
XML.NewComment(Comment: = 'MyComment');
*)
METHOD PUBLIC NewComment
VAR_INPUT
Comment : T_MaxString;
END_VAR
IF TagOpen THEN
XmlBuffer.Append := TAG_CLOSE;
TagOpen := FALSE;
END_IF;
XmlBuffer.Append := OPEN_COMMENT;
XmlBuffer.Append := Comment;
XmlBuffer.Append := CLOSE_COMMENT;
Comment
T_MaxString
¶
NewParameter
PUBLIC
¶
Must
be called after opening a new tag
XML.NewParameter(Name: = 'ParaName', Value: = 'Value');
Inputs
Source Code
(*
Must be called after opening a new tag
XML.NewParameter(Name: = 'ParaName', Value: = 'Value');
*)
METHOD PUBLIC NewParameter
VAR_INPUT
Name : T_MaxString;
Value : T_MaxString;
END_VAR
XmlBuffer.Append := SPACE;
XmlBuffer.Append := Name;
XmlBuffer.Append := EQUALS;
XmlBuffer.Append := QUOTE;
XmlBuffer.Append := Value;
XmlBuffer.Append := QUOTE;
NewTag
PUBLIC
¶
Creates
a new Tag:
XML:
XML.NewTag(Name: = 'MyTag');
Inputs
Source Code
(*
Creates a new Tag:
XML: <MyTag>
XML.NewTag(Name: = 'MyTag');
*)
METHOD PUBLIC NewTag
VAR_INPUT
Name : T_MaxString;
END_VAR
IF TagOpen THEN
XmlBuffer.Append := TAG_CLOSE;
END_IF;
XmlBuffer.Append := TAG_OPEN;
XmlBuffer.Append := Name;
TagOpen := TRUE;
TagListBuffer.Append := FORWARD_SLASH;
TagListBuffer.Append := Name;
Name
T_MaxString
¶
NewTagData
PUBLIC
¶
SetBuffer
PUBLIC
¶
Inputs
-
PointerToBuffer
–ADR(..)
-
SizeOfBuffer
–SIZEOF(..)
Source Code
METHOD PUBLIC SetBuffer
VAR_INPUT
PointerToBuffer : POINTER TO BYTE; // ADR(..)
SizeOfBuffer : UDINT; // SIZEOF(..)
END_VAR
XmlBuffer.SetBuffer(PointerToBufferAddress:= PointerToBuffer, SizeOfBuffer := SizeOfBuffer);
TagListBuffer.SetBuffer(PointerToBufferAddress := ADR(Tags), SizeOfBuffer := SIZEOF(Tags));
TagListSeekBuffer.SetBuffer(PointerToBufferAddress := ADR(TagsSeek), SizeOfBuffer := SIZEOF(TagsSeek));
TagBuffer.SetBuffer(PointerToBufferAddress := ADR(Tag), SizeOfBuffer := SIZEOF(Tag));
ToStartBuffer
PUBLIC
¶
Jump
to the beginning of the XML data XML.ToStartBuffer();
Source Code
(*
Jump to the beginning of the XML data
XML.ToStartBuffer();
*)
METHOD PUBLIC ToStartBuffer
SearchPosition := 0;
TagListSeekBuffer.Length := 0;
TagsSeek := '';
Tag := '';
WriteDocumentHeader
PUBLIC
¶
Add
your own preffered fileheader like: XML:
Start with calling this method before appending any other tags!
XML.WriteDocumentHeader('<?xml version="1.0" encoding="UTF-8"?>');
Inputs
Source Code
(*
Add your own preffered fileheader like:
XML: <?xml version="1.0" encoding="UTF-8"?>
Start with calling this method before appending any other tags!
XML.WriteDocumentHeader('<?xml version="1.0" encoding="UTF-8"?>');
*)
METHOD PUBLIC WriteDocumentHeader
VAR_INPUT
Header : T_MaxString;
END_VAR
XmlBuffer.Append := Header;
Header
T_MaxString
¶
Length
UDINT
Get
¶
Source Code
Length := XmlBuffer.Length;
F_AnyToUnionValue
¶
Inputs
Source Code
FUNCTION F_AnyToUnionValue : U_ExpectedOrActual
VAR_INPUT
AnySize : UDINT;
AnyTypeClass : IBaseLibrary.TypeClass;
AnyValue : POINTER TO BYTE;
END_VAR
CASE AnyTypeClass OF
IBaseLibrary.TypeClass.TYPE_BOOL :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.boolExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_BIT :
{warning disable C0355}
MEMCPY(destaddr := ADR(F_AnyToUnionValue.bitExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
{warning enable C0355}
IBaseLibrary.TypeClass.TYPE_BYTE :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.byteExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_WORD :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.wordExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_DWORD :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.dwordExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_LWORD :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.lwordExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_SINT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.sintExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_INT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.intExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_DINT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.dintExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_LINT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.lintExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_USINT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.usintExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_UINT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.uintExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_UDINT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.udintExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_ULINT :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.ulintExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_REAL :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.realExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_LREAL :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.lrealExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_STRING :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.stringExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_WSTRING :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.wstringExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_TIME :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.timeExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_DATE :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.dateExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_DATEANDTIME :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.dateandtimeExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_TIMEOFDAY :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.timeofdayExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_POINTER :
// None
IBaseLibrary.TypeClass.TYPE_REFERENCE :
// None
IBaseLibrary.TypeClass.TYPE_SUBRANGE :
// None
IBaseLibrary.TypeClass.TYPE_ENUM :
// None
IBaseLibrary.TypeClass.TYPE_ARRAY :
// None
IBaseLibrary.TypeClass.TYPE_PARAMS :
// None
IBaseLibrary.TypeClass.TYPE_USERDEF :
// None
IBaseLibrary.TypeClass.TYPE_NONE :
// None
IBaseLibrary.TypeClass.TYPE_ANY :
// None
IBaseLibrary.TypeClass.TYPE_ANYBIT :
// None
IBaseLibrary.TypeClass.TYPE_ANYDATE :
// None
IBaseLibrary.TypeClass.TYPE_ANYINT :
// None
IBaseLibrary.TypeClass.TYPE_ANYNUM :
// None
IBaseLibrary.TypeClass.TYPE_ANYREAL :
// None
IBaseLibrary.TypeClass.TYPE_LAZY :
// None
IBaseLibrary.TypeClass.TYPE_LTIME :
MEMCPY(destaddr := ADR(F_AnyToUnionValue.ltimeExpectedOrActual),
srcAddr := AnyValue,
n := AnySize);
IBaseLibrary.TypeClass.TYPE_BITCONST :
// None
IBaseLibrary.TypeClass.TYPE_INTERFACE :
// None
ELSE
// None
END_CASE
F_AnyTypeClassToString
¶
Inputs
Source Code
// This function takes the type-class of a ANY-variable and returns the STRING representation of it.
FUNCTION F_AnyTypeClassToString : STRING
VAR_INPUT
AnyTypeClass : __SYSTEM.TYPE_CLASS;
END_VAR
CASE UDINT_TO_INT(AnyTypeClass) OF
IBaseLibrary.TypeClass.TYPE_BOOL :
F_AnyTypeClassToString := 'BOOL';
IBaseLibrary.TypeClass.TYPE_BIT :
F_AnyTypeClassToString := 'BIT';
IBaseLibrary.TypeClass.TYPE_BYTE :
F_AnyTypeClassToString := 'BYTE';
IBaseLibrary.TypeClass.TYPE_WORD :
F_AnyTypeClassToString := 'WORD';
IBaseLibrary.TypeClass.TYPE_DWORD :
F_AnyTypeClassToString := 'DWORD';
IBaseLibrary.TypeClass.TYPE_LWORD :
F_AnyTypeClassToString := 'LWORD';
IBaseLibrary.TypeClass.TYPE_SINT :
F_AnyTypeClassToString := 'SINT';
IBaseLibrary.TypeClass.TYPE_INT :
F_AnyTypeClassToString := 'INT';
IBaseLibrary.TypeClass.TYPE_DINT :
F_AnyTypeClassToString := 'DINT';
IBaseLibrary.TypeClass.TYPE_LINT :
F_AnyTypeClassToString := 'LINT';
IBaseLibrary.TypeClass.TYPE_USINT :
F_AnyTypeClassToString := 'USINT';
IBaseLibrary.TypeClass.TYPE_UINT :
F_AnyTypeClassToString := 'UINT';
IBaseLibrary.TypeClass.TYPE_UDINT :
F_AnyTypeClassToString := 'UDINT';
IBaseLibrary.TypeClass.TYPE_ULINT :
F_AnyTypeClassToString := 'ULINT';
IBaseLibrary.TypeClass.TYPE_REAL :
F_AnyTypeClassToString := 'REAL';
IBaseLibrary.TypeClass.TYPE_LREAL :
F_AnyTypeClassToString := 'LREAL';
IBaseLibrary.TypeClass.TYPE_STRING :
F_AnyTypeClassToString := 'STRING';
IBaseLibrary.TypeClass.TYPE_WSTRING :
F_AnyTypeClassToString := 'WSTRING';
IBaseLibrary.TypeClass.TYPE_TIME :
F_AnyTypeClassToString := 'TIME';
IBaseLibrary.TypeClass.TYPE_DATE :
F_AnyTypeClassToString := 'DATE';
IBaseLibrary.TypeClass.TYPE_DATEANDTIME :
F_AnyTypeClassToString := 'DATEANDTIME';
IBaseLibrary.TypeClass.TYPE_TIMEOFDAY :
F_AnyTypeClassToString := 'TIMEOFDAY';
IBaseLibrary.TypeClass.TYPE_POINTER :
F_AnyTypeClassToString := 'POINTER';
IBaseLibrary.TypeClass.TYPE_REFERENCE :
F_AnyTypeClassToString := 'REFERENCE';
IBaseLibrary.TypeClass.TYPE_SUBRANGE :
F_AnyTypeClassToString := 'SUBRANGE';
IBaseLibrary.TypeClass.TYPE_ENUM :
F_AnyTypeClassToString := 'ENUM';
IBaseLibrary.TypeClass.TYPE_ARRAY :
F_AnyTypeClassToString := 'ARRAY';
IBaseLibrary.TypeClass.TYPE_PARAMS :
F_AnyTypeClassToString := 'PARAMS';
IBaseLibrary.TypeClass.TYPE_USERDEF :
F_AnyTypeClassToString := 'USERDEF';
IBaseLibrary.TypeClass.TYPE_NONE :
F_AnyTypeClassToString := 'NONE';
IBaseLibrary.TypeClass.TYPE_ANY :
F_AnyTypeClassToString := 'ANY';
IBaseLibrary.TypeClass.TYPE_ANYBIT :
F_AnyTypeClassToString := 'ANYBIT';
IBaseLibrary.TypeClass.TYPE_ANYDATE :
F_AnyTypeClassToString := 'ANYDATE';
IBaseLibrary.TypeClass.TYPE_ANYINT :
F_AnyTypeClassToString := 'ANYINT';
IBaseLibrary.TypeClass.TYPE_ANYNUM :
F_AnyTypeClassToString := 'ANYNUM';
IBaseLibrary.TypeClass.TYPE_ANYREAL :
F_AnyTypeClassToString := 'ANYREAL';
IBaseLibrary.TypeClass.TYPE_LAZY :
F_AnyTypeClassToString := 'LAZY';
IBaseLibrary.TypeClass.TYPE_LTIME :
F_AnyTypeClassToString := 'LTIME';
IBaseLibrary.TypeClass.TYPE_BITCONST :
F_AnyTypeClassToString := 'BITCONST';
IBaseLibrary.TypeClass.TYPE_INTERFACE :
F_AnyTypeClassToString := 'INTERFACE';
ELSE
F_AnyTypeClassToString := 'UNKNOWN';
END_CASE
AnyTypeClass
__SYSTEM.TYPE_CLASS
¶
F_AssertionTypeToString
¶
Inputs
Source Code
(* Since TwinCAT 3.1.4024.x it's possible to do TO_STRING on enumerations,
but for backward compability we need to do it manually *)
FUNCTION F_AssertionTypeToString : T_MaxString
VAR_INPUT
AssertionType : E_AssertionType;
END_VAR
CASE AssertionType OF
E_AssertionType.Type_UNDEFINED :
F_AssertionTypeToString := 'UNDEFINED';
E_AssertionType.Type_ANY :
F_AssertionTypeToString := 'ANY';
(* Primitive types *)
E_AssertionType.Type_BOOL :
F_AssertionTypeToString := 'BOOL';
E_AssertionType.Type_BYTE :
F_AssertionTypeToString := 'BYTE';
E_AssertionType.Type_DATE :
F_AssertionTypeToString := 'DATE';
E_AssertionType.Type_DATE_AND_TIME :
F_AssertionTypeToString := 'DATE_AND_TIME';
E_AssertionType.Type_DINT :
F_AssertionTypeToString := 'DINT';
E_AssertionType.Type_DWORD :
F_AssertionTypeToString := 'DWORD';
E_AssertionType.Type_INT :
F_AssertionTypeToString := 'INT';
E_AssertionType.Type_LINT :
F_AssertionTypeToString := 'LINT';
E_AssertionType.Type_LREAL :
F_AssertionTypeToString := 'LREAL';
E_AssertionType.Type_LTIME :
F_AssertionTypeToString := 'LTIME';
E_AssertionType.Type_LWORD :
F_AssertionTypeToString := 'LWORD';
E_AssertionType.Type_REAL :
F_AssertionTypeToString := 'REAL';
E_AssertionType.Type_SINT :
F_AssertionTypeToString := 'SINT';
E_AssertionType.Type_STRING :
F_AssertionTypeToString := 'STRING';
E_AssertionType.Type_TIME :
F_AssertionTypeToString := 'TIME';
E_AssertionType.Type_TIME_OF_DAY :
F_AssertionTypeToString := 'TIME_OF_DAY';
E_AssertionType.Type_UDINT :
F_AssertionTypeToString := 'UDINT';
E_AssertionType.Type_UINT :
F_AssertionTypeToString := 'UINT';
E_AssertionType.Type_ULINT :
F_AssertionTypeToString := 'ULINT';
E_AssertionType.Type_USINT :
F_AssertionTypeToString := 'USINT';
E_AssertionType.Type_WORD :
F_AssertionTypeToString := 'WORD';
E_AssertionType.Type_WSTRING :
F_AssertionTypeToString := 'WSTRING';
(* Array types *)
E_AssertionType.Type_Array2D_LREAL :
F_AssertionTypeToString := 'Array2D_LREAL';
E_AssertionType.Type_Array2D_REAL :
F_AssertionTypeToString := 'Array2D_REAL';
E_AssertionType.Type_Array3D_LREAL :
F_AssertionTypeToString := 'Array3D_LREAL';
E_AssertionType.Type_Array3D_REAL :
F_AssertionTypeToString := 'Array3D_REAL';
E_AssertionType.Type_Array_BOOL :
F_AssertionTypeToString := 'Array_BOOL';
E_AssertionType.Type_Array_BYTE :
F_AssertionTypeToString := 'Array_BYTE';
E_AssertionType.Type_Array_DINT :
F_AssertionTypeToString := 'Array_DINT';
E_AssertionType.Type_Array_DWORD :
F_AssertionTypeToString := 'Array_DWORD';
E_AssertionType.Type_Array_INT :
F_AssertionTypeToString := 'Array_INT';
E_AssertionType.Type_Array_LINT :
F_AssertionTypeToString := 'Array_LINT';
E_AssertionType.Type_Array_LREAL :
F_AssertionTypeToString := 'Array_LREAL';
E_AssertionType.Type_Array_LWORD :
F_AssertionTypeToString := 'Array_LWORD';
E_AssertionType.Type_Array_REAL :
F_AssertionTypeToString := 'Array_REAL';
E_AssertionType.Type_Array_SINT :
F_AssertionTypeToString := 'Array_SINT';
E_AssertionType.Type_Array_UDINT :
F_AssertionTypeToString := 'Array_UDINT';
E_AssertionType.Type_Array_UINT :
F_AssertionTypeToString := 'Array_UINT';
E_AssertionType.Type_Array_ULINT :
F_AssertionTypeToString := 'Array_ULINT';
E_AssertionType.Type_Array_USINT :
F_AssertionTypeToString := 'Array_USINT';
E_AssertionType.Type_Array_WORD :
F_AssertionTypeToString := 'Array_WORD';
ELSE
F_AssertionTypeToString := 'UNDEFINED';
END_CASE
AssertionType
E_AssertionType
¶
F_GetCpuCounterAs64bit
¶
In/Outputs
Source Code
(* Calls the passed GETCPUCOUNTER function block and
converts the output of the GETCPUCOUNTER function block from 2x32bit variables to a
single 64bit variable
*)
FUNCTION F_GetCpuCounterAs64bit : LWORD
VAR_IN_OUT CONSTANT
CpuCounter : GETCPUCOUNTER;
END_VAR
CpuCounter();
F_GetCpuCounterAs64bit := SHL(DWORD_TO_LWORD(CpuCounter.cpuCntHiDW), 32) + DWORD_TO_LWORD(CpuCounter.cpuCntLoDW);
CpuCounter
GETCPUCOUNTER
¶
F_GetTestSuiteNameFromTestInstancePath
¶
Inputs
Source Code
FUNCTION F_GetTestSuiteNameFromTestInstancePath : T_MaxString
VAR_INPUT
TestInstancePath : T_MaxString;
END_VAR
VAR
TestSuiteName : T_MaxString;
FindPosition : INT;
END_VAR
TestSuiteName := F_RemoveInstancePathAndProjectNameFromTestInstancePath(TestInstancePath := TestInstancePath);
// Remove everything except the test suite name
FindPosition := FIND(STR1 := TestSuiteName, '.');
TestSuiteName := RIGHT(STR := TestSuiteName, SIZE := LEN(STR := TestSuiteName) - FindPosition);
F_GetTestSuiteNameFromTestInstancePath := TestSuiteName;
TestInstancePath
T_MaxString
¶
F_IsAnyEqualToUnionValue
¶
Inputs
Source Code
FUNCTION F_IsAnyEqualToUnionValue : BOOL
VAR_INPUT
ExpectedOrActual : U_ExpectedOrActual;
ExpectedOrActualSize : UDINT;
ExpectedOrActualTypeClass : IBaseLibrary.TypeClass;
ExpectedOrActualValue : POINTER TO BYTE;
END_VAR
VAR
AnyExpectedOrActual : U_ExpectedOrActual;
END_VAR
AnyExpectedOrActual := F_AnyToUnionValue(AnySize := ExpectedOrActualSize,
AnyTypeClass := ExpectedOrActualTypeClass,
AnyValue := ExpectedOrActualValue);
CASE ExpectedOrActualTypeClass OF
IBaseLibrary.TypeClass.TYPE_BOOL :
F_IsAnyEqualToUnionValue := ExpectedOrActual.boolExpectedOrActual = AnyExpectedOrActual.boolExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_BIT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.bitExpectedOrActual = AnyExpectedOrActual.bitExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_BYTE :
F_IsAnyEqualToUnionValue := ExpectedOrActual.byteExpectedOrActual = AnyExpectedOrActual.byteExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_WORD :
F_IsAnyEqualToUnionValue := ExpectedOrActual.wordExpectedOrActual = AnyExpectedOrActual.wordExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_DWORD :
F_IsAnyEqualToUnionValue := ExpectedOrActual.dwordExpectedOrActual = AnyExpectedOrActual.dwordExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_LWORD :
F_IsAnyEqualToUnionValue := ExpectedOrActual.lwordExpectedOrActual = AnyExpectedOrActual.lwordExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_SINT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.sintExpectedOrActual = AnyExpectedOrActual.sintExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_INT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.intExpectedOrActual = AnyExpectedOrActual.intExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_DINT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.dintExpectedOrActual = AnyExpectedOrActual.dintExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_LINT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.lintExpectedOrActual = AnyExpectedOrActual.lintExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_USINT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.usintExpectedOrActual = AnyExpectedOrActual.usintExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_UINT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.uintExpectedOrActual = AnyExpectedOrActual.uintExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_UDINT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.udintExpectedOrActual = AnyExpectedOrActual.udintExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_ULINT :
F_IsAnyEqualToUnionValue := ExpectedOrActual.ulintExpectedOrActual = AnyExpectedOrActual.ulintExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_REAL :
F_IsAnyEqualToUnionValue := ExpectedOrActual.realExpectedOrActual = AnyExpectedOrActual.realExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_LREAL :
F_IsAnyEqualToUnionValue := ExpectedOrActual.lrealExpectedOrActual = AnyExpectedOrActual.lrealExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_STRING :
F_IsAnyEqualToUnionValue := ExpectedOrActual.stringExpectedOrActual = AnyExpectedOrActual.stringExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_WSTRING :
F_IsAnyEqualToUnionValue := ExpectedOrActual.wstringExpectedOrActual = AnyExpectedOrActual.wstringExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_TIME :
F_IsAnyEqualToUnionValue := ExpectedOrActual.timeExpectedOrActual = AnyExpectedOrActual.timeExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_DATE :
F_IsAnyEqualToUnionValue := ExpectedOrActual.dateExpectedOrActual = AnyExpectedOrActual.dateExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_DATEANDTIME :
F_IsAnyEqualToUnionValue := ExpectedOrActual.dateandtimeExpectedOrActual = AnyExpectedOrActual.dateandtimeExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_TIMEOFDAY :
F_IsAnyEqualToUnionValue := ExpectedOrActual.timeofdayExpectedOrActual = AnyExpectedOrActual.timeofdayExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_POINTER :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_REFERENCE :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_SUBRANGE :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ENUM :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ARRAY :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_PARAMS :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_USERDEF :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_NONE :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ANY :
(* Even though the data input of the ExpectedOrActual is ANY, this CASE-switch will never
enter this case, but instead the type-class that it is an instance of. So for instance,
if the ExpectedOrActual is an instance of INT, this case-switch will enter the
IBaseLibrary.TypeClass.TYPE_INT case. *)
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ANYBIT :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ANYDATE :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ANYINT :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ANYNUM :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_ANYREAL :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_LAZY :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_LTIME :
F_IsAnyEqualToUnionValue := ExpectedOrActual.ltimeExpectedOrActual = AnyExpectedOrActual.ltimeExpectedOrActual;
IBaseLibrary.TypeClass.TYPE_BITCONST :
F_IsAnyEqualToUnionValue := FALSE;
IBaseLibrary.TypeClass.TYPE_INTERFACE :
F_IsAnyEqualToUnionValue := FALSE;
ELSE
F_IsAnyEqualToUnionValue := FALSE;
END_CASE
F_RemoveInstancePathAndProjectNameFromTestInstancePath
¶
Inputs
Source Code
FUNCTION F_RemoveInstancePathAndProjectNameFromTestInstancePath : T_MaxString
VAR_INPUT
TestInstancePath : T_MaxString;
END_VAR
VAR
CharacterPositionOfProjectName : INT;
ProjectNameWithDot : T_MaxString;
END_VAR
// Add the '.' character to the project name for search
ProjectNameWithDot := CONCAT(STR1 := TwinCAT_SystemInfoVarList._AppInfo.ProjectName, STR2 := '.');
// Find the character position of the beginning of the first occurence of the project name
CharacterPositionOfProjectName := FIND(STR1 := TestInstancePath, STR2 := ProjectNameWithDot);
IF CharacterPositionOfProjectName > 0 THEN
TestInstancePath := DELETE(STR := TestInstancePath,
LEN := CharacterPositionOfProjectName-1 + LEN(ProjectNameWithDot),
POS := 1);
END_IF
// Check if the project name happens to be the same as namespace, and in that case, remove that as well
CharacterPositionOfProjectName := FIND(STR1 := TestInstancePath,
STR2 := ProjectNameWithDot);
IF CharacterPositionOfProjectName > 0 THEN
TestInstancePath := DELETE(STR := TestInstancePath,
LEN := CharacterPositionOfProjectName - 1 + LEN(STR := ProjectNameWithDot),
POS := 1);
END_IF
F_RemoveInstancePathAndProjectNameFromTestInstancePath := TestInstancePath;
TestInstancePath
T_MaxString
¶
IS_TEST_FINISHED
¶
Inputs
Source Code
// Check if a certain test in the current suite is finished
FUNCTION IS_TEST_FINISHED : BOOL
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
Counter : UINT;
CurrentTest : FB_Test;
END_VAR
TestName := F_LTrim(in := F_RTrim(in := TestName));
IS_TEST_FINISHED := FALSE;
FOR Counter := 1 TO GVL_TcUnit.CurrentTestSuiteBeingCalled^.GetNumberOfTests() BY 1 DO
CurrentTest := GVL_TcUnit.CurrentTestSuiteBeingCalled^.Tests[Counter];
IF CurrentTest.TestName = TestName THEN
IS_TEST_FINISHED := CurrentTest.IsFinished();
RETURN;
END_IF
END_FOR
TestName
T_MaxString
¶
RUN
¶
This
function runs all test suites that have been initialized. The test suites are run in parallel (all at once).
Source Code
(*
This function runs all test suites that have been initialized.
The test suites are run in parallel (all at once).
*)
FUNCTION RUN
GVL_TcUnit.TcUnitRunner.RunTestSuiteTests();
RUN_IN_SEQUENCE
¶
This
function runs all test suites that have been initialized. The test suites are run in sequence (one after the other).
Source Code
(*
This function runs all test suites that have been initialized.
The test suites are run in sequence (one after the other).
*)
FUNCTION RUN_IN_SEQUENCE
GVL_TcUnit.TcUnitRunner.RunTestSuiteTestsInSequence(TimeBetweenTestSuitesExecution := GVL_Param_TcUnit.TimeBetweenTestSuitesExecution);
TCUNIT_ADSLOGSTR
¶
Inputs
-
msgCtrlMask
–Message control mask
-
msgFmtStr
–Message format string
-
strArg
–STRING argument
Source Code
(* This function allows to put ADS strings into the TcUnit ADS message buffer. If ADSLOGSTR() is used directly,
the messages can come out of sequence in relation to the message created by TcUnit as TcUnit buffers the messages to
not overflow the ADS message router. By using this function, the ADS-messages are put in the same buffer as
TcUnit is using for its output and thus the sequence will be correct *)
FUNCTION TCUNIT_ADSLOGSTR
VAR_INPUT
msgCtrlMask : DWORD; // Message control mask
msgFmtStr : T_MaxString; // Message format string
strArg : T_MaxString; // STRING argument
END_VAR
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := msgCtrlMask,
MsgFmtStr := msgFmtStr,
StrArg := strArg);
TEST
¶
Inputs
Source Code
// This function declares a new test (if it has not been already declared in an earlier cycle)
FUNCTION TEST
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
CounterTestSuiteAddress : UINT;
Test : REFERENCE TO FB_Test;
END_VAR
TestName := F_LTrim(in := F_RTrim(in := TestName));
// Mark this test as the current one being executed
GVL_TcUnit.CurrentTestNameBeingCalled := TestName;
(* Check if combination of address for the test suite and test name already exists.
For every test suite the name of the test case needs to be unique.
If a test with this name already exists, don't add it to the available tests.
Otherwise, add it to the available tests *)
FOR CounterTestSuiteAddress := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO
// Look for the test suite by comparing to the one that is currently running
IF GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN
Test REF= GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress]^.AddTest(TestName := TestName, IsTestOrdered := FALSE);
GVL_TcUnit.CurrentTestIsFinished := GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress]^.IsTestFinished(TestName := TestName);
IF __ISVALIDREF(Test) THEN
Test.SetStartedAtIfNotSet(Timestamp := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter));
END_IF
RETURN;
END_IF
END_FOR
TestName
T_MaxString
¶
TEST_FINISHED
¶
Source Code
// Sets the currently running test as finished
FUNCTION TEST_FINISHED : BOOL
VAR
TestName : T_MaxString;
Counter : UINT := 0;
FinishedAt : LWORD;
END_VAR
// Get the timestamp directly when the test has finished
FinishedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter);
// Grab the currently running test name
TestName := GVL_TcUnit.CurrentTestNameBeingCalled;
TEST_FINISHED := FALSE;
(* Find the test suite and:
1. Set the test in that test suite as finished
2. Calculate and set the number of asserts made for that test
*)
FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO
IF GVL_TcUnit.TestSuiteAddresses[Counter] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN
GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := GVL_TcUnit.CurrentTestNameBeingCalled, FinishedAt := FinishedAt);
GVL_TcUnit.TestSuiteAddresses[Counter]^.CalculateAndSetNumberOfAssertsForTest(TestName := GVL_TcUnit.CurrentTestNameBeingCalled);
GVL_TcUnit.CurrentTestIsFinished := TRUE;
TEST_FINISHED := TRUE;
RETURN;
END_IF
END_FOR
TEST_FINISHED_NAMED
¶
Inputs
Source Code
(* Sets a test defined by TestName as finished. Note that the TestName-input must match
a TestName that has been previously defined in this test suite. *)
FUNCTION TEST_FINISHED_NAMED
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
Counter : UINT := 0;
FoundTestName : BOOL := FALSE;
FinishedAt : LWORD; // cpu cycle counter in 100ns precision
END_VAR
VAR_STAT
FailedLookupCounter : UINT := 0;
AlreadyPrintedFinalWarning : BOOL := FALSE;
END_VAR
VAR CONSTANT
MaxNumberOfNonExistentTestNamesFailedLookups : UINT := 3;
END_VAR
TestName := F_LTrim(in := F_RTrim(in := TestName));
FinishedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter);
(* Find the test suite and:
1. Set the test in that test suite as finished
2. Calculate and set the number of asserts made for that test
*)
FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO
IF GVL_TcUnit.TestSuiteAddresses[Counter] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN
FoundTestName := GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := TestName, FinishedAt := FinishedAt);
IF NOT FoundTestName THEN
IF FailedLookupCounter < MaxNumberOfNonExistentTestNamesFailedLookups THEN
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := 'Failed to find test $'%s$'',
StrArg := TestName);
FailedLookupCounter := FailedLookupCounter + 1;
(* Abort TcUnit *)
GVL_TcUnit.TcUnitRunner.AbortRunningTestSuiteTests();
ELSIF NOT AlreadyPrintedFinalWarning THEN
GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := ADSLOG_MSGTYPE_ERROR,
MsgFmtStr := 'Excess failed attempts to mark test finished, failed. Further warnings will be suppressed',
StrArg := TestName);
AlreadyPrintedFinalWarning := TRUE;
END_IF
ELSE
GVL_TcUnit.TestSuiteAddresses[Counter]^.CalculateAndSetNumberOfAssertsForTest(TestName := TestName);
GVL_TcUnit.CurrentTestIsFinished := TRUE;
END_IF
RETURN;
END_IF
END_FOR
TestName
T_MaxString
¶
TEST_ORDERED
¶
Inputs
Source Code
(* This function declares a new ordered test (if it has not been already declared in an earlier cycle).
The test declared by this function will run in the order it is called, so if we have two tests:
TEST_ORDERED('Test_1')
TEST_ORDERED('Test_2')
All asserts of Test_2 will be ignored until Test_1 is declared with TEST_FINISHED().
The function returns TRUE if it's time to run this test (and thus asserts can be made)
The function returns FALSE if it's not time to run this test (because a previous test has not been finished)
If the function returns FALSE (and it's thus not time to run the test), any eventual asserts done for this
test will be ignored. It thus makes sense to call this function in a manner like:
IF TEST_ORDERED('Testname') THEN
fbFunctionBlockUnderTest();
AssertEquals(Expected := 'SomeValue',
Actual := fbFunctionBlockUnderTest.Out,
Message := 'Test failed');
TEST_FINISHED();
END_IF
*)
FUNCTION TEST_ORDERED : BOOL
VAR_INPUT
TestName : T_MaxString;
END_VAR
VAR
CounterTestSuiteAddress : UINT;
Test : REFERENCE TO FB_Test;
END_VAR
TestName := F_LTrim(in := F_RTrim(in := TestName));
// Mark this test as the current one being executed
GVL_TcUnit.CurrentTestNameBeingCalled := TestName;
(* Check if combination of address for the test suite and test name already exists.
For every test suite the name of the test case needs to be unique.
If a test with this name already exists, don't add it to the available tests.
Otherwise, add it to the available tests *)
FOR CounterTestSuiteAddress := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO
// Look for the test suite by comparing to the one that is currently running
IF GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN
Test REF= GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress]^.AddTest(TestName := TestName, IsTestOrdered := TRUE);
GVL_TcUnit.CurrentTestIsFinished := GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress]^.IsTestFinished(TestName := TestName);
// Check that no previous code has set the currently running test to ignored (for example by setting the test to DISABLED
IF NOT GVL_TcUnit.IgnoreCurrentTest THEN
(* If the current test is not the current in the sequence of tests, set it to ignored until it is its turn to run
If the current test is the one supposed to be run, check whether it has finished running or not *)
IF GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress]^.GetTestOrderNumber(TestName := TestName) =
GVL_TcUnit.CurrentlyRunningOrderedTestInTestSuite[CounterTestSuiteAddress] THEN
// Check if test if finished, if so, increase the order number of this test suite to the next test
IF GVL_TcUnit.CurrentTestIsFinished THEN
GVL_TcUnit.CurrentlyRunningOrderedTestInTestSuite[CounterTestSuiteAddress] := GVL_TcUnit.CurrentlyRunningOrderedTestInTestSuite[CounterTestSuiteAddress] + 1;
// No need to execute the test if it is already finished
TEST_ORDERED := FALSE;
GVL_TcUnit.IgnoreCurrentTest := TRUE;
ELSE
// Start or continue executing test
IF __ISVALIDREF(Test) THEN
Test.SetStartedAtIfNotSet(Timestamp := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter));
END_IF
TEST_ORDERED := TRUE;
END_IF
ELSE
// If this is not the current test that we are supposed to run, ignore it until it is its turn
TEST_ORDERED := FALSE;
GVL_TcUnit.IgnoreCurrentTest := TRUE;
END_IF
// This test should be ignored
ELSE
TEST_ORDERED := FALSE;
GVL_TcUnit.IgnoreCurrentTest := TRUE;
END_IF
RETURN;
END_IF
END_FOR
TestName
T_MaxString
¶
WRITE_PROTECTED_BOOL
¶
WRITE_PROTECTED_BYTE
¶
WRITE_PROTECTED_DATE
¶
WRITE_PROTECTED_DATE_AND_TIME
¶
WRITE_PROTECTED_DINT
¶
WRITE_PROTECTED_DWORD
¶
WRITE_PROTECTED_INT
¶
WRITE_PROTECTED_LREAL
¶
WRITE_PROTECTED_REAL
¶
WRITE_PROTECTED_SINT
¶
WRITE_PROTECTED_STRING
¶
WRITE_PROTECTED_WSTRING
¶
WRITE_PROTECTED_TIME
¶
WRITE_PROTECTED_TIME_OF_DAY
¶
WRITE_PROTECTED_UDINT
¶
WRITE_PROTECTED_UINT
¶
WRITE_PROTECTED_ULINT
¶
WRITE_PROTECTED_LWORD
¶
WRITE_PROTECTED_LINT
¶
WRITE_PROTECTED_USINT
¶
WRITE_PROTECTED_WORD
¶
E_AssertionType
¶
Source Code
{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_AssertionType :
(
Type_UNDEFINED := 0,
Type_ANY,
// Primitive types
Type_BOOL,
Type_BYTE,
Type_DATE,
Type_DATE_AND_TIME,
Type_DINT,
Type_DWORD,
Type_INT,
Type_LINT,
Type_LREAL,
Type_LTIME,
Type_LWORD,
Type_REAL,
Type_SINT,
Type_STRING,
Type_TIME,
Type_TIME_OF_DAY,
Type_UDINT,
Type_UINT,
Type_ULINT,
Type_USINT,
Type_WORD,
Type_WSTRING,
// Array types
Type_Array2D_LREAL,
Type_Array2D_REAL,
Type_Array3D_LREAL,
Type_Array3D_REAL,
Type_Array_BOOL,
Type_Array_BYTE,
Type_Array_DINT,
Type_Array_DWORD,
Type_Array_INT,
Type_Array_LINT,
Type_Array_LREAL,
Type_Array_LWORD,
Type_Array_REAL,
Type_Array_SINT,
Type_Array_UDINT,
Type_Array_UINT,
Type_Array_ULINT,
Type_Array_USINT,
Type_Array_WORD
) BYTE;
END_TYPE
E_XmlError
¶
Source Code
{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_XmlError :
(
Ok := 0,
ErrorMaxBufferLen := 1,
ErrorStringLen := 2,
Error := 3
) BYTE;
END_TYPE
ST_AdsLogStringMessage
¶
ST_AssertResult
¶
ST_AssertResultInstances
¶
Source Code
TYPE ST_AssertResultInstances :
STRUCT
AssertResult : ST_AssertResult;
DetectionCount : UINT; // Number of instances of the "AssertResult"
DetectionCountThisCycle : UINT; // Number of instance of the "AssertResult" in this specific PLC-cycle
END_STRUCT
END_TYPE
AssertResult
ST_AssertResult
¶
DetectionCount
UINT
¶
Number of instances of the "AssertResult"
DetectionCountThisCycle
UINT
¶
Number of instance of the "AssertResult" in this specific PLC-cycle
ST_AssertArrayResult
¶
Source Code
TYPE ST_AssertArrayResult :
STRUCT
ExpectedsSize : UDINT; // Size in bytes of the expecteds-array
ExpectedsTypeClass : IBaseLibrary.TypeClass; // The data type of the expecteds-array
ActualsSize : UDINT; // Size in bytes of the actuals-array
ActualsTypeClass : IBaseLibrary.TypeClass; // The data type of the actuals-array
Message : T_MaxString;
TestInstancePath : T_MaxString;
END_STRUCT
END_TYPE
ExpectedsSize
UDINT
¶
Size in bytes of the expecteds-array
ExpectedsTypeClass
IBaseLibrary.TypeClass
¶
The data type of the expecteds-array
ActualsSize
UDINT
¶
Size in bytes of the actuals-array
ActualsTypeClass
IBaseLibrary.TypeClass
¶
The data type of the actuals-array
Message
T_MaxString
¶
TestInstancePath
T_MaxString
¶
ST_AssertArrayResultInstances
¶
Source Code
TYPE ST_AssertArrayResultInstances :
STRUCT
AssertArrayResult : ST_AssertArrayResult;
DetectionCount : UINT; // Number of instances of the "AssertArrayResult"
DetectionCountThisCycle : UINT; // Number of instance of the "AssertArrayResult" in this specific PLC-cycle
END_STRUCT
END_TYPE
AssertArrayResult
ST_AssertArrayResult
¶
DetectionCount
UINT
¶
Number of instances of the "AssertArrayResult"
DetectionCountThisCycle
UINT
¶
Number of instance of the "AssertArrayResult" in this specific PLC-cycle
ST_TestCaseResult
¶
Source Code
TYPE ST_TestCaseResult :
STRUCT
TestName : T_MaxString;
TestClassName : T_MaxString;
TestIsFailed : BOOL;
TestIsSkipped : BOOL;
FailureMessage : T_MaxString;
FailureType : E_AssertionType;
NumberOfAsserts : UINT;
Duration : LREAL; // in seconds
END_STRUCT
END_TYPE
TestName
T_MaxString
¶
TestClassName
T_MaxString
¶
TestIsFailed
BOOL
¶
TestIsSkipped
BOOL
¶
FailureMessage
T_MaxString
¶
FailureType
E_AssertionType
¶
NumberOfAsserts
UINT
¶
Duration
LREAL
¶
in seconds
ST_TestSuiteResult
¶
Source Code
TYPE ST_TestSuiteResult :
STRUCT
Name : T_MaxString; // Full class name
Identity : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestSuites); // Should be 0..GVL_Param_TcUnit.MaxNumberOfTestSuites-1 but gives unknown compiler error
NumberOfTests : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
NumberOfFailedTests : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
Duration : LREAL; // In seconds
TestCaseResults : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF ST_TestCaseResult;
END_STRUCT
END_TYPE
Name
T_MaxString
¶
Full class name
Identity
UINT(0..GVL_Param_TcUnit.MaxNumberOfTestSuites)
¶
Should be 0..GVL_Param_TcUnit.MaxNumberOfTestSuites-1 but gives unknown compiler error
NumberOfTests
UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)
¶
NumberOfFailedTests
UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)
¶
Duration
LREAL
¶
In seconds
TestCaseResults
ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF ST_TestCaseResult
¶
ST_TestSuiteResults
¶
Source Code
TYPE ST_TestSuiteResults :
STRUCT
// General test results
NumberOfTestSuites : UINT; // The total number of test suites
NumberOfTestCases : UINT; // The total number of test cases (for all test suites)
NumberOfSuccessfulTestCases : UINT; // The total number of test cases that had all ASSERTS successful
NumberOfFailedTestCases : UINT; // The total number of test cases that had at least one ASSERT failed
Duration : LREAL; // Duration it took for all test suites to finish, in seconds
// Test results for each individiual test suite
TestSuiteResults : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestSuites] OF ST_TestSuiteResult;
END_STRUCT
END_TYPE
NumberOfTestSuites
UINT
¶
The total number of test suites
NumberOfTestCases
UINT
¶
The total number of test cases (for all test suites)
NumberOfSuccessfulTestCases
UINT
¶
The total number of test cases that had all ASSERTS successful
NumberOfFailedTestCases
UINT
¶
The total number of test cases that had at least one ASSERT failed
Duration
LREAL
¶
Duration it took for all test suites to finish, in seconds
TestSuiteResults
ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestSuites] OF ST_TestSuiteResult
¶
U_ExpectedOrActual
¶
Source Code
TYPE U_ExpectedOrActual :
UNION
boolExpectedOrActual : BOOL;
bitExpectedOrActual : BIT;
byteExpectedOrActual : BYTE;
dwordExpectedOrActual : DWORD;
lwordExpectedOrActual : LWORD;
stringExpectedOrActual : T_MaxString;
udintExpectedOrActual : UDINT;
uintExpectedOrActual : UINT;
usintExpectedOrActual : USINT;
sintExpectedOrActual : SINT;
intExpectedOrActual : INT;
wordExpectedOrActual : WORD;
dintExpectedOrActual : DINT;
lintExpectedOrActual : LINT;
ulintExpectedOrActual : ULINT;
realExpectedOrActual : REAL;
lrealExpectedOrActual : LREAL;
wstringExpectedOrActual : WSTRING(255);
timeExpectedOrActual : TIME;
ltimeExpectedOrActual : LTIME;
dateExpectedOrActual : DATE;
dateandtimeExpectedOrActual : DATE_AND_TIME;
timeofdayExpectedOrActual : TIME_OF_DAY;
END_UNION
END_TYPE
GVL_Param_TcUnit
¶
Source Code
{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
MaxNumberOfTestSuites : UINT := 1000;
MaxNumberOfTestsForEachTestSuite : UINT := 100;
MaxNumberOfAssertsForEachTestSuite : UINT := 1000;
(* TcUnit logs complete test results. These include:
- Number of test suites
- Number of tests
- Number of successful tests
- Number of failed tests
- Any eventual failed assertion (with the expected & actual value plus an user defined message)
These are all printed to the ADS logger (Visual Studio error list) marked with ERROR criticality
On top of this TcUnit also reports some statistics/extended information with HINT/INFO criticality.
These statistics are more detailed results of the tests. This information is used when results are
being collected by an external software (such as TcUnit-Runner) to do for example Jenkins integration.
This extra information however takes time to print, so by setting the following parameter to FALSE
it will speed up TcUnit finishing. *)
LogExtendedResults : BOOL := TRUE;
(* Enable (TRUE) or disable (FALSE) publishing of the xUnit Xml report *)
xUnitEnablePublish : BOOL := FALSE;
(* Default reserved PLC memory buffer used for composition of the xUnit xml file (64 kb default) *)
xUnitBufferSize : UDINT := 65535;
(* Default path and filename for the xunit testresults e.g.: for use with jenkins
Use environment variables for a OS independent file path
- %TC_BOOTPRJPATH% -> 'C:\TwinCAT\3.1\Boot\' (Windows), '/usr/local/etc/TwinCAT/3.1/Boot/' (TC/BSD), '\Hard Disk\TwinCAT\3.1\Boot\' (Windows CE)
- %TC_INSTALLPATH% -> 'C:\TwinCAT\3.1\' (Windows), '/usr/local/etc/TwinCAT/3.1/' (TC/BSD), '\Hard Disk\TwinCAT\3.1\' (Windows CE) *)
xUnitFilePath : T_MaxString := '%TC_BOOTPRJPATH%tcunit_xunit_testresults.xml';
(* This is the maximum number of ADS-messages that can be stored for reporting at the same time.
Having a size of 2000 means that it's possible to report up to ~400 test cases in one single
PLC cycle. Each entry consumes around 500 bytes, so with an example of a ring buffer size of
2000 it means that TcUnit will consume around 1 MB of router memory. *)
AdsLogMessageFifoRingBufferSize : UINT := 2000;
(* Time delay between a test suite is finished and the execution of the next test suite starts
if using RUN_IN_SEQUENCE() *)
TimeBetweenTestSuitesExecution : TIME := T#0MS;
END_VAR
MaxNumberOfTestSuites
UINT
¶
MaxNumberOfTestsForEachTestSuite
UINT
¶
MaxNumberOfAssertsForEachTestSuite
UINT
¶
LogExtendedResults
BOOL
¶
xUnitEnablePublish
BOOL
¶
xUnitBufferSize
UDINT
¶
xUnitFilePath
T_MaxString
¶
AdsLogMessageFifoRingBufferSize
UINT
¶
TimeBetweenTestSuitesExecution
TIME
¶
GVL_TcUnit
¶
Source Code
{attribute 'no_assign'}
{attribute 'qualified_only'}
VAR_GLOBAL
TcUnitRunner : FB_TcUnitRunner;
(* Indication of whether the last instantiated test suite has an assert instance created *)
TestSuiteIsRegistered : BOOL;
(* Pointer to current test suite being called *)
CurrentTestSuiteBeingCalled : POINTER TO FB_TestSuite;
(* Current name of test being called *)
CurrentTestNameBeingCalled : T_MaxString;
(* Used to get the current cpu cycle counter to calculate the duration of tests and test suits, respectively *)
GetCpuCounter : GETCPUCOUNTER;
(* Stores the CPU cycle count with 100ns precision since the first entry into one of the Run methods (RUN, RUN_IN_SEQUENCE) *)
StartedAt : LWORD;
(* Duration it took for a complete run, in seconds *)
Duration : LREAL;
(* Whether or not the current test being called has finished running *)
CurrentTestIsFinished : BOOL;
(* This is a flag that indicates that the current test should be ignored, and
thus that all assertions under it should be ignored as well. A test can be ignored either
because the user has requested so, or because the test is a duplicate name *)
IgnoreCurrentTest : BOOL;
(* The assert function block instance should be 1:1 mapped to
the test suite instance path. *)
NumberOfInitializedTestSuites : UINT := 0;
TestSuiteAddresses : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestSuites] OF POINTER TO FB_TestSuite;
(* If the user is utilizing the TEST_ORDERED(), we need to keep track of which ordered test is currently running.
We do this by defining an array, in where we can see which current TEST_ORDERED() is the one to be handled right now.
The below array is only used for TEST_ORDERED()-tests. *)
CurrentlyRunningOrderedTestInTestSuite : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestSuites] OF UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
(* Buffered ADS message queue for output to the error list *)
AdsMessageQueue : FB_AdsLogStringMessageFifoQueue;
END_VAR
VAR_GLOBAL CONSTANT
(* Multiply a value that is given in 100ns units by this value to
convert the value to seconds *)
HundredNanosecondToSecond : LREAL := 1.0 / 10000000.0;
END_VAR
TcUnitRunner
FB_TcUnitRunner
¶
TestSuiteIsRegistered
BOOL
¶
CurrentTestSuiteBeingCalled
POINTER TO FB_TestSuite
¶
CurrentTestNameBeingCalled
T_MaxString
¶
GetCpuCounter
GETCPUCOUNTER
¶
StartedAt
LWORD
¶
Duration
LREAL
¶
CurrentTestIsFinished
BOOL
¶
IgnoreCurrentTest
BOOL
¶
NumberOfInitializedTestSuites
UINT
¶
TestSuiteAddresses
ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestSuites] OF POINTER TO FB_TestSuite
¶
CurrentlyRunningOrderedTestInTestSuite
ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestSuites] OF UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)
¶
AdsMessageQueue
FB_AdsLogStringMessageFifoQueue
¶
HundredNanosecondToSecond
LREAL
¶
Global_Version
¶
Source Code
{attribute 'TcGenerated'}
{attribute 'no-analysis'}
{attribute 'linkalways'}
// This function has been automatically generated from the project information.
VAR_GLOBAL CONSTANT
{attribute 'const_non_replaced'}
stLibVersion_TcUnit : ST_LibVersion := (iMajor := 1, iMinor := 3, iBuild := 2, iRevision := 0, nFlags := 0, sVersion := '1.3.2');
END_VAR