FB_TestSuite Function Block

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'}


Variables

NameTypeDefaultDescription
InstancePathT_MaxString
GetCurrentTaskIndexGETCURTASKINDEX
NumberOfTestsUINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)0
TestsARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF FB_Test
TestDuplicateNameTriggerARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF R_TRIG
TestCycleCountIndexARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF UDINT
AssertResultsFB_AssertResultStatic
AssertArrayResultsFB_AssertArrayResultStatic
AdsAssertMessageFormatterFB_AdsAssertMessageFormatter
AssertMessageFormatterI_AssertMessageFormatterAdsAssertMessageFormatter
StartedAtLWORD
DurationLREAL
NumberOfOrderedTestsUINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)

Methods

AddTest INTERNAL

Parameters

NameTypeDescription
TestNameT_MaxString
IsTestOrderedBOOL
Implementation
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

Parameters

NameTypeDescription
TestInstancePathT_MaxString
Implementation
CompleteTestInstancePath := CONCAT(STR1 := TestInstancePath, STR2 := '@');
AddTestNameToInstancePath := CONCAT(STR1 := CompleteTestInstancePath, STR2 := GVL_TcUnit.CurrentTestNameBeingCalled);
AreAllTestsFinished PUBLIC
Implementation
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

Asserts that two LREAL 2D-arrays are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
DeltaLREALThe 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
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*,*] OF LREALLREAL 2d array with expected values
ActualsARRAY[*,*] OF LREALLREAL 2d array with actual values
Implementation
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
AssertArray2dEquals_REAL PUBLIC

Asserts that two REAL 2D-arrays are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
DeltaREALThe 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
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*,*] OF REALREAL 2d array with expected values
ActualsARRAY[*,*] OF REALREAL 2d array with actual values
Implementation
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
AssertArray3dEquals_LREAL PUBLIC

Asserts that two LREAL 3D-arrays are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
DeltaLREALThe 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
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*,*,*] OF LREALLREAL 3d array with expected values
ActualsARRAY[*,*,*] OF LREALLREAL 3d array with actual values
Implementation
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
AssertArray3dEquals_REAL PUBLIC

Asserts that two REAL 3D-arrays are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
DeltaREALThe 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
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*,*,*] OF REALREAL 3d array with expected values
ActualsARRAY[*,*,*] OF REALREAL 3d array with actual values
Implementation
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
AssertArrayEquals_BOOL PUBLIC

Asserts that two BOOL arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF BOOLBOOL array with expected values
ActualsARRAY[*] OF BOOLBOOL array with actual values
Implementation
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

Asserts that two BYTE arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF BYTEBYTE array with expected values
ActualsARRAY[*] OF BYTEBYTE array with actual values
Implementation
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

Asserts that two DINT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF DINTDINT array with expected values
ActualsARRAY[*] OF DINTDINT array with actual values
Implementation
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

Asserts that two DWORD arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF DWORDDWORD array with expected values
ActualsARRAY[*] OF DWORDDWORD array with actual values
Implementation
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

Asserts that two INT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF INTINT array with expected values
ActualsARRAY[*] OF INTINT array with actual values
Implementation
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

Asserts that two LINT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF LINTLINT array with expected values
ActualsARRAY[*] OF LINTLINT array with actual values
Implementation
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

Asserts that two LREAL arrays are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
DeltaLREALThe 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
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF LREALLREAL array with expected values
ActualsARRAY[*] OF LREALLREAL array with actual values
Implementation
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
AssertArrayEquals_LWORD PUBLIC

Asserts that two LWORD arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF LWORDLWORD array with expected values
ActualsARRAY[*] OF LWORDLWORD array with actual values
Implementation
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

Asserts that two REAL arrays are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
DeltaREALThe 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
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF REALREAL array with expected values
ActualsARRAY[*] OF REALREAL array with actual values
Implementation
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
AssertArrayEquals_SINT PUBLIC

Asserts that two SINT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF SINTSINT array with expected values
ActualsARRAY[*] OF SINTSINT array with actual values
Implementation
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

Asserts that two UDINT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF UDINTUDINT array with expected values
ActualsARRAY[*] OF UDINTUDINT array with actual values
Implementation
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

Asserts that two UINT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF UINTUINT array with expected values
ActualsARRAY[*] OF UINTUINT array with actual values
Implementation
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

Asserts that two ULINT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF ULINTULINT array with expected values
ActualsARRAY[*] OF ULINTULINT array with actual values
Implementation
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

Asserts that two USINT arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF USINTUSINT array with expected values
ActualsARRAY[*] OF USINTUSINT array with actual values
Implementation
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

Asserts that two WORD arrays are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
MessageT_MaxStringThe identifying message for the assertion error

In/Out

NameTypeDescription
ExpectedsARRAY[*] OF WORDWORD array with expected values
ActualsARRAY[*] OF WORDWORD array with actual values
Implementation
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.

Parameters

NameTypeDescription
ExpectedANYExpected value
ActualANYThe value to check against expected
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two BOOLs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedBOOLBOOL expected value
ActualBOOLBOOL actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two BYTEs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedBYTEBYTE expected value
ActualBYTEBYTE actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two DATEs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedDATEDATE expected value
ActualDATEDATE actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two DATE_AND_TIMEs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedDATE_AND_TIMEDATE_AND_TIME expected value
ActualDATE_AND_TIMEDATE_AND_TIME actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two DINTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedDINTDINT expected value
ActualDINTDINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two DWORDs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedDWORDDWORD expected value
ActualDWORDDWORD actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two INTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedINTINT expected value
ActualINTINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two LINTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedLINTLINT expected value
ActualLINTLINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two LREALs are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedLREALLREAL expected value
ActualLREALLREAL actual value
DeltaLREALThe maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two LTIMEs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedLTIMELTIME expected value
ActualLTIMELTIME actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two LWORDs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedLWORDLWORD expected value
ActualLWORDLWORD actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two REALs are equal to within a positive delta. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedREALREAL expected value
ActualREALREAL actual value
DeltaREALThe maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two SINTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedSINTSINT expected value
ActualSINTSINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two STRINGs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedT_MaxStringSTRING expected value
ActualT_MaxStringSTRING actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two TIMEs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedTIMETIME expected value
ActualTIMETIME actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two TIME_OF_DAYs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedTIME_OF_DAYTIME_OF_DAY expected value
ActualTIME_OF_DAYTIME_OF_DAY actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two UDINTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedUDINTUDINT expected value
ActualUDINTUDINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two UINTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedUINTUINT expected value
ActualUINTUINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two ULINTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedULINTULINT expected value
ActualULINTULINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two USINTs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedUSINTUSINT expected value
ActualUSINTUSINT actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two WORDs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedWORDWORD expected value
ActualWORDWORD actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that two WSTRINGs are equal. If they are not, an assertion error is created.

Parameters

NameTypeDescription
ExpectedWSTRING(255)WSTRING expected value
ActualWSTRING(255)WSTRING actual value
MessageT_MaxStringThe identifying message for the assertion error
Implementation
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

Asserts that a condition is false. If it is not, an assertion error is created.

Parameters

NameTypeDescription
ConditionBOOLCondition to be checked
MessageT_MaxStringThe identifying message for the assertion error
Implementation
AssertEquals_BOOL(Expected := FALSE,
                  Actual := Condition,
                  Message := Message);
AssertTrue PUBLIC

Asserts that a condition is true. If it is not, an assertion error is created.

Parameters

NameTypeDescription
ConditionBOOLCondition to be checked
MessageT_MaxStringThe identifying message for the assertion error
Implementation
AssertEquals_BOOL(Expected := TRUE,
                  Actual := Condition,
                  Message := Message);
CalculateAndSetNumberOfAssertsForTest INTERNAL

Parameters

NameTypeDescription
TestNameT_MaxString
Implementation
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
CalculateDuration INTERNAL

Parameters

NameTypeDescription
FinishedAtLWORDCPU cycle counter with 100ns precision
Implementation
IF Duration = 0.0 THEN
	Duration := LWORD_TO_LREAL(FinishedAt - StartedAt) * GVL_TcUnit.HundredNanosecondToSecond; // Seconds
END_IF
FB_init : BOOL

Parameters

NameTypeDescription
bInitRetainsBOOLif TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCodeBOOLif TRUE, the instance afterwards gets moved into the copy code (online change)
Implementation
GVL_TcUnit.NumberOfInitializedTestSuites := GVL_TcUnit.NumberOfInitializedTestSuites + 1;
GVL_TcUnit.TestSuiteAddresses[GVL_TcUnit.NumberOfInitializedTestSuites] := THIS;
FindTestSuiteInstancePath PRIVATE

Searches for the instance path of the calling function block

Implementation
FindTestSuiteInstancePath := GetInstancePath();
GetDuration INTERNAL
Implementation
GetDuration := Duration;
GetHasStartedRunning INTERNAL
Implementation
GetHasStartedRunning := StartedAt > 0;
GetInstancePath INTERNAL
Implementation
GetInstancePath := InstancePath;
GetNumberOfFailedTests INTERNAL
Implementation
// 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
Implementation
// 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
Implementation
GetNumberOfSuccessfulTests := GetNumberOfTests() - GetNumberOfFailedTests() - GetNumberOfSkippedTests();
GetNumberOfTests INTERNAL
Implementation
GetNumberOfTests := NumberOfTests;
GetNumberOfTestsToAnalyse INTERNAL
Implementation
GetNumberOfTestsToAnalyse := MIN(GetNumberOfTests(), GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite);
GetTestByName : REFERENCE

Parameters

NameTypeDescription
TestNameT_MaxString
Implementation
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
GetTestByPosition INTERNAL

This method returns the test at the n'th position, ranging from 1.. NumberOfTests

Parameters

NameTypeDescription
PositionUINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)
Implementation
GetTestByPosition := Tests[Position];
GetTestOrderNumber INTERNAL

Parameters

NameTypeDescription
TestNameT_MaxString
Implementation
// 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
IsTestFinished INTERNAL

Parameters

NameTypeDescription
TestNameT_MaxString
Implementation
// 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
SetStartedAtIfNotSet INTERNAL

Parameters

NameTypeDescription
TimestampLWORDCPU cycle counter with 100ns precision
Implementation
IF StartedAt = 0 THEN
    StartedAt := Timestamp;
END_IF
SetStartedAtTimeBasedOnCpuCounter INTERNAL
Implementation
StartedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter);
SetTestFailed PRIVATE

Parameters

NameTypeDescription
AssertionTypeE_AssertionType
AssertionMessageT_MaxString
Implementation
// 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

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

Parameters

NameTypeDescription
TestNameT_MaxString
FinishedAtLWORD
Implementation
// 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;

Used by

Declaration source
(* 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