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

Name Type Default Description
InstancePath T_MaxString
GetCurrentTaskIndex GETCURTASKINDEX
NumberOfTests UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite) 0
Tests ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF FB_Test
TestDuplicateNameTrigger ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF R_TRIG
TestCycleCountIndex ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF UDINT
AssertResults FB_AssertResultStatic
AssertArrayResults FB_AssertArrayResultStatic
AdsAssertMessageFormatter FB_AdsAssertMessageFormatter
AssertMessageFormatter I_AssertMessageFormatter AdsAssertMessageFormatter
StartedAt LWORD
Duration LREAL
NumberOfOrderedTests UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)

Methods

AddTest INTERNAL

Parameters

Name Type Description
TestName T_MaxString
IsTestOrdered BOOL
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

Name Type Description
TestInstancePath T_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

Name Type Description
Delta LREAL The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*,*] OF LREAL LREAL 2d array with expected values
Actuals ARRAY[*,*] OF LREAL LREAL 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

Name Type Description
Delta REAL The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*,*] OF REAL REAL 2d array with expected values
Actuals ARRAY[*,*] OF REAL REAL 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

Name Type Description
Delta LREAL The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*,*,*] OF LREAL LREAL 3d array with expected values
Actuals ARRAY[*,*,*] OF LREAL LREAL 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

Name Type Description
Delta REAL The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*,*,*] OF REAL REAL 3d array with expected values
Actuals ARRAY[*,*,*] OF REAL REAL 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF BOOL BOOL array with expected values
Actuals ARRAY[*] OF BOOL BOOL 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF BYTE BYTE array with expected values
Actuals ARRAY[*] OF BYTE BYTE 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF DINT DINT array with expected values
Actuals ARRAY[*] OF DINT DINT 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF DWORD DWORD array with expected values
Actuals ARRAY[*] OF DWORD DWORD 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF INT INT array with expected values
Actuals ARRAY[*] OF INT INT 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF LINT LINT array with expected values
Actuals ARRAY[*] OF LINT LINT 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

Name Type Description
Delta LREAL The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF LREAL LREAL array with expected values
Actuals ARRAY[*] OF LREAL LREAL 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF LWORD LWORD array with expected values
Actuals ARRAY[*] OF LWORD LWORD 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

Name Type Description
Delta REAL The maximum delta between the value of expected and actual for which both numbers are still considered equal, proportional to the expected value in that array cell
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF REAL REAL array with expected values
Actuals ARRAY[*] OF REAL REAL 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF SINT SINT array with expected values
Actuals ARRAY[*] OF SINT SINT 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF UDINT UDINT array with expected values
Actuals ARRAY[*] OF UDINT UDINT 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF UINT UINT array with expected values
Actuals ARRAY[*] OF UINT UINT 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF ULINT ULINT array with expected values
Actuals ARRAY[*] OF ULINT ULINT 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF USINT USINT array with expected values
Actuals ARRAY[*] OF USINT USINT 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

Name Type Description
Message T_MaxString The identifying message for the assertion error

In/Out

Name Type Description
Expecteds ARRAY[*] OF WORD WORD array with expected values
Actuals ARRAY[*] OF WORD WORD 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

Name Type Description
Expected ANY Expected value
Actual ANY The value to check against expected
Message T_MaxString The 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

Name Type Description
Expected BOOL BOOL expected value
Actual BOOL BOOL actual value
Message T_MaxString The 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

Name Type Description
Expected BYTE BYTE expected value
Actual BYTE BYTE actual value
Message T_MaxString The 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

Name Type Description
Expected DATE DATE expected value
Actual DATE DATE actual value
Message T_MaxString The 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

Name Type Description
Expected DATE_AND_TIME DATE_AND_TIME expected value
Actual DATE_AND_TIME DATE_AND_TIME actual value
Message T_MaxString The identifying message for the assertion error
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

Name Type Description
Expected DINT DINT expected value
Actual DINT DINT actual value
Message T_MaxString The 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

Name Type Description
Expected DWORD DWORD expected value
Actual DWORD DWORD actual value
Message T_MaxString The 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

Name Type Description
Expected INT INT expected value
Actual INT INT actual value
Message T_MaxString The 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

Name Type Description
Expected LINT LINT expected value
Actual LINT LINT actual value
Message T_MaxString The 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

Name Type Description
Expected LREAL LREAL expected value
Actual LREAL LREAL actual value
Delta LREAL The maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
Message T_MaxString The identifying message for the assertion error
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

Name Type Description
Expected LTIME LTIME expected value
Actual LTIME LTIME actual value
Message T_MaxString The 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

Name Type Description
Expected LWORD LWORD expected value
Actual LWORD LWORD actual value
Message T_MaxString The 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

Name Type Description
Expected REAL REAL expected value
Actual REAL REAL actual value
Delta REAL The maximum delta between the absolute value of expected and actual for which both numbers are still considered equal
Message T_MaxString The identifying message for the assertion error
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

Name Type Description
Expected SINT SINT expected value
Actual SINT SINT actual value
Message T_MaxString The 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

Name Type Description
Expected T_MaxString STRING expected value
Actual T_MaxString STRING actual value
Message T_MaxString The 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

Name Type Description
Expected TIME TIME expected value
Actual TIME TIME actual value
Message T_MaxString The 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

Name Type Description
Expected TIME_OF_DAY TIME_OF_DAY expected value
Actual TIME_OF_DAY TIME_OF_DAY actual value
Message T_MaxString The identifying message for the assertion error
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

Name Type Description
Expected UDINT UDINT expected value
Actual UDINT UDINT actual value
Message T_MaxString The 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

Name Type Description
Expected UINT UINT expected value
Actual UINT UINT actual value
Message T_MaxString The 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

Name Type Description
Expected ULINT ULINT expected value
Actual ULINT ULINT actual value
Message T_MaxString The 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

Name Type Description
Expected USINT USINT expected value
Actual USINT USINT actual value
Message T_MaxString The 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

Name Type Description
Expected WORD WORD expected value
Actual WORD WORD actual value
Message T_MaxString The 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

Name Type Description
Expected WSTRING(255) WSTRING expected value
Actual WSTRING(255) WSTRING actual value
Message T_MaxString The 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

Name Type Description
Condition BOOL Condition to be checked
Message T_MaxString The 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

Name Type Description
Condition BOOL Condition to be checked
Message T_MaxString The identifying message for the assertion error
Implementation
AssertEquals_BOOL(Expected := TRUE,
                  Actual := Condition,
                  Message := Message);
CalculateAndSetNumberOfAssertsForTest INTERNAL

Parameters

Name Type Description
TestName T_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

Name Type Description
FinishedAt LWORD CPU 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

Name Type Description
bInitRetains BOOL if TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCode BOOL if TRUE, the instance afterwards gets moved into the copy code (online change)
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

Name Type Description
TestName T_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

Name Type Description
Position UINT(1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite)
Implementation
GetTestByPosition := Tests[Position];
GetTestOrderNumber INTERNAL

Parameters

Name Type Description
TestName T_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

Name Type Description
TestName T_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

Name Type Description
Timestamp LWORD CPU 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

Name Type Description
AssertionType E_AssertionType
AssertionMessage T_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

Name Type Description
TestName T_MaxString
FinishedAt LWORD
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