ASSERT-F and ASSERT-T (Test an assertion)
| Free-Form Syntax | ASSERT-F{(A)} condition |
ASSERT-T{(A)} condition |
|
ASSERT-F{(A)} condition %MSG(message-text) |
|
ASSERT-T{(A)} condition %MSG(message-text) |
|
ASSERT-F{(A)} condition %MSG(message-id : message-file {: replacement-text}) |
|
ASSERT-T{(A)} condition %MSG(message-id : message-file {: replacement-text}) |
| Code | Factor 1 | Extended Factor 2 | ||||
|---|---|---|---|---|---|---|
ASSERT-F{(A)} |
expression {%MSG} |
|||||
ASSERT-T{(A)} |
expression {%MSG} |
|||||
Assertion statements provide a self-documenting way to verify correctness. For example, you can check pre-conditions at the beginning of a procedure and check post-conditions at the end of a procedure.
-
During development of your application, you operate in
ASSERT(*EXCP)mode so your application fails immediately with an exception if an assertion fails. - After your application is deployed, if you don't want your application to fail immediately:
- Use
ASSERT(*WARN)mode if you want the information about the failed assertion to appear in the joblog to aid in problem determination later. - Use
ASSERT(*NONE)mode to completely disable the assertions.
- Use
Assertion statements in ASSERT(*CALL) mode
may be useful in a unit-testing environment since
the specified program or procedure is called for every assertion statement indicating
whether the assertion succeeded or failed.
ASSERT-F operation to assert that a condition is false.
In the following example, the programmer is asserting that variable n
is not zero.
ASSERT-F n = 0 %MSG('n = 0!');
p = x / n;
ASSERT-T operation to assert that a condition is true.
In the following example, the programmer is asserting that the array index is still
less than the number of elements in the array.
ASSERT-T (index < %elem(arr)) %MSG('The array is too small');
index += 1;
arr(index) = new_value;
The first operand of an assertion statement is the condition to be checked.
%MSG built-in function.
For the assertion operations, %MSG allows a single message-text
parameter.
This form of %MSG is valid in all modes.
See Rules for %MSG with one parameter.
- For the
ASSERT(*CALL)mode, you must use the form of%MSGwhich only allows one message-text parameter. The message-text parameter of%MSGis passed as the second parameter for the called program or procedure for every assertion operation.No message is sent to the joblog in
ASSERT(*CALL)mode for a failed assertion. - For the
ASSERT(*EXCP)andASSERT(*WARN)modes:- You can use the form of
%MSGwith only one parameter. In this case, messageRNX0461is sent. The message-text parameter of%MSGis used for the replacement text of the message. - You can also use the form of
%MSGwhich allows you to specify a message id and message file. If an error occurs while sending the message, such as the message file not being found, the statement fails with status code 00126 (Error sending a message).
- You can use the form of
- For the
ASSERT(*NONE)mode, you can use either form of%MSG.
The A operation extender can be used to specify that the assertion
statement always operates in ASSERT(*EXCP) mode unless
the ASSERT(*CALL) mode is in effect.
ASSERT Control keyword controls
how assertion operations are handled at compile time and run time.
- With the default mode of
ASSERT(*EXCP), if the assertion fails, an escape message is sent at run time to the procedure containing the assertion statement. Status code 00461 is set. - With the
ASSERT(*WARN)mode, if the assertion fails, a diagnostic message is sent at run time to the procedure containing the assertion statement unless theAoperation extender is specified indicating that the statement should always operate inASSERT(*EXCP)mode. No status code is associated with a failed assertion withASSERT(*WARN). - With the
ASSERT(*NONE)mode, assertion statements are ignored at compile time unless theAoperation extender is specified indicating that the statement should always operate inASSERT(*EXCP)mode. - With
ASSERT(*CALL:prototype-name) mode, the program or procedure identified by the prototype-name is called for every assertion statement at run time with a parameter indicating whether the assertion failed. See Rules for the prototype specified by ASSERT(*CALL:prototype-name).
Rules for %MSG with one parameter
The operand can be character, UCS-2, or graphic.
- For the
ASSERT(*EXCP)andASSERT(*WARN)modes, the parameter is used as the replacement text for messageRNX0461.It cannot be longer than 5000 characters when converted to the job CCSID.
If the operand is not valid, the error message has one of the following reason codes:CCSID_GRAPH_IGNORE:CCSID(*GRAPH:*IGNORE)cannot be in effect if the operand has type graphic.CVT_LEN_GT_5000: The length of the operand might be greater than 5000 when converted to the job CCSID.DATATYPE: The operand must have type character, UCS-2 or graphic.FIGCON: It cannot be a figurative constant.LEN_GT_5000: The length is greater than 5000.
- For the
ASSERT(*CALL)mode, it must be valid for the second parameter of the specified prototype-name.
Rules for the prototype specified by ASSERT(*CALL:prototype-name)
The prototype can be for a program or procedure. If the procedure is defined in the same module, it is not necessary to explicitly code the prototype.
CONST keyword must be specified for every parameter.
- The first parameter is required.
It must have type indicator.
*ONis passed to this parameter if the assertion was successful and*OFFis passed if the assertion failed. ForASSERT-F, the assertion is successful if the condition is false and forASSERT-T, the assertion is successful if the condition is true. -
The second parameter is required.
It must have type character, UCS-2, or graphic.
The message-text operand of
%MSGis passed to this parameter. - The third parameter is optional.
If it is specified, it must have type
CHARorVARCHARwithCCSID(*UTF8). (TheCCSIDparameter can also be specified asCCSID(1208).) The name of the procedure containing theASSERT-ForASSERT-Toperation is passed to this parameter. The "declaration case" of the procedure name is used.If the
ASSERT-ForASSERT-Toperation is in the cycle-main procedure, the name of the procedure is the same as the name of the module being created. - The fourth parameter is optional.
If it is specified, it must have type
UNS(10)orUNS(20). The statement number of theASSERT-ForASSERT-Tis passed to this parameter.
JAVA_METHOD: The prototype cannot be a Java™ method.OVERLOAD: The prototype cannot have theOVERLOADkeyword.RETVAL: The prototype cannot have a return value.
Example of ASSERT(*EXCP)
- The
ASSERTkeyword is not specified in the Control options so the program defaults toASSERT(*EXCP)mode. - The
ASSERT-Fcondition indicates that the programmer expects the conditionitem_id = 0 OR qty = 0to be false. If eitheritem_id = 0orqty = 0, the assertion fails. Since%MSGis specified with only one parameter, escape messageRNX0461is issued indicating that the assertion failed.The program will fail with status code 00461.
- The
ASSERT-Tcondition indicates that the programmer expects the conditiontotal <= MAXto be true. If the condition is false, an escape message is sent. Since%MSGis specified with more than one parameter, escape messageORD0101in message file ORDERMSGF is issued indicating that the nature of the problem.The program will fail with status code 00461.
CTL-OPT DFTACTGRP(*NO); // 1
...
ASSERT-F price = 0 OR qty = 0 %MSG('price, qty cannot be zero'); // 2
...
ASSERT-T total <= MAX %MSG('ORD0101' : 'ORDERMSGF' : %char(total)); // 3
...
Example of ASSERT(*WARN) with the A operation extender
A operation extender is specified for a specific assertion
statement, a failed assertion causes an escape message to be sent.
- The
ASSERT(*WARN)keyword is specified. - The
ASSERT-Fcondition indicates that the programmer expects the conditionqty = 0to be false. If the assertion fails, the diagnostic message will appear in the joblog, but the program will continue. - The
ASSERT-Tcondition indicates that the programmer expects the conditiontotal <= MAXto be true. If the assertion fails, theAoperation extender will cause an escape message to be sent.The program will fail with status code 00461.
CTL-OPT ASSERT(*WARN); // 1
...
ASSERT-F qty = 0 %MSG('qty cannot be zero'); // 2
...
ASSERT-T(A) total <= MAX %MSG('total is too big'); // 3
...
Example of ASSERT(*NONE) with the A operation extender
A operation extender is specified for a specific assertion
statement, a failed assertion causes an escape message to be sent.
- The
ASSERT(*NONE)keyword is specified. - The
ASSERT-Fcondition indicates that the programmer expects the conditionqty = 0to be false. However, this assertion is not checked by the compiler. - The
ASSERT-Tcondition indicates that the programmer expects the conditiontotal <= MAXto be true. If the assertion fails, theAoperation extender will cause an escape message to be sent.The program will fail with status code 00461.
CTL-OPT ASSERT(*NONE); // 1
...
ASSERT-F qty = 0 %MSG('qty cannot be zero'); // 2
...
ASSERT-T(A) total <= MAX %MSG('total is too big'); // 3
...
Example of ASSERT(*CALL) where the procedure has 2 parameters
- The program is in
ASSERT(*CALL)mode. - The
ASSERT-Fcondition indicates that the programmer expects the conditionitem_id = 0 OR qty = 0to be false. - In this program, the
ASSERT(*CALL)procedure is in the module so it was not necessary to code the prototype. - The
okparameter is*OFFif the assertion failed and*ONotherwise. If it was theASSERT-Foperation code,okwould be*ONif the condition was false. - The procedure calls another procedure to log the result of the assertion statement.
- If the module is compiled with
DEFINE(ASSERT_ERR_TO_JOBLOG), a failed assertion will cause an escape message to be sent to the calling procedure, which is the procedure with the assertion statement. This allows the module to behave almost as though bothASSERT(*CALL)andASSERT(*EXCP)were in effect. The difference is that the status code in the procedure with the failed assertion statement will be status code 00211, the status code for a failed call, instead of 00461, the status code for a failed assertion.
CTL-OPT ASSERT(*CALL : chkAssert); // 1
...
ASSERT-F price = 0 OR qty = 0 %MSG('price, qty cannot be zero'); // 2
...
DCL-PROC chkAssert; // 3
DCL-PI *N;
ok IND CONST; // 4
msg VARCHAR(100) CONST;
END-PI;
log_result (ok : msg); // 5
/IF DEFINED(ASSERT_ERR_TO_JOBLOG) // 6
IF NOT ok;
SND-MSG *ESCAPE 'Assertion error: ' + msg;
ENDIF;
/ENDIF
END-PROC;
Example of ASSERT(*CALL) where the procedure has 4 parameters
In the following example, procedure chkAssert is called for every assertion statement.
The example shows an excerpt from the compile listing, showing the
statement numbers.
The source was compiled with OPTION(*SRCSTMT) so the
statement numbers are derived from the source sequence numbers.
If the source had been compiled with OPTION(*NOSRCSTMT), the
statement numbers would be sequential (1, 2, 3, and so on).
- The program is in
ASSERT(*CALL)mode. The procedure called for everyASSERT-ForASSERT-Toperation is chkAssert4Parms. - The
ASSERT-Tstatement is in the cycle-main procedure. The name passed as the third parameter of the chkAssert4Parms procedure is the name of the program or module being created. The statement number passed as the fourth parameter is 500. - The symbolic name of the procedure is
PROC1. The declaration case of the procedure name isProc1. - The name passed as the third parameter of the chkAssert4Parms
procedure is
"Proc1". The statement number passed as the fourth parameter is 1000.
S o u r c e L i s t i n g
000100 CTL-OPT ASSERT(*CALL : chkAssert4Parms); // 1
000200
000300 DCL-S n INT(10);
000400
000500 ASSERT-T n = 1 %MSG('N should be 1.'); // 2
000600 proc1 ();
000700 RETURN;
000800
000900 DCL-PROC Proc1; // 3
001000 ASSERT-T n = 2 %MSG('N should be 2'); // 4
001100 END-PROC;
001200
001300 DCL-PROC chkAssert4Parms;
001400 DCL-PI *N;
001500 ok IND CONST;
001600 msg VARCHAR(100) CONST;
001700 procName VARCHAR(50) CCSID(*UTF8) CONST;
001800 stmt UNS(10) CONST;
001900 END-PI;
002000 // ...
002100 END-PROC;
