views:

323

answers:

3

What is the best way of implementing assertions using Progress 4GL or WebSpeed?

+1  A: 

Since Progress doesn't have native handling for assertions, but best I've come up with is:

IF NOT <assertion> THEN
RUN assertionFailed.p.

assertionFailed.p can email the programmer, or log the conditions and also exit gracefully.

Kevin Rettig
+1  A: 

Given that assertions are generally omitted from the final code I'd suggest the preprocessor route. You might do something like the following set it up as two include files. When you are compiling it to production ensure that the debugalert.i is empty. assert.i could be edited to do whatever you like message, stop, email etc...

To setup an assertion you would just follow the format {assert.i &condition=}


/* assert.i */ {debugalert.i}

&IF DEFINED( DEBUGALERT ) <> 0 &THEN

IF NOT {&CONDITION} THEN DO:

MESSAGE THIS-PROCEDURE:FILENAME "ERROR...{&CONDITION}" 
    VIEW-AS ALERT-BOX.
/* add code to email message etc.. or stop */

END.

&ENDIF


/* debugalert.i on test or development environments to turn off the assertions remove this statement */

&GLOBAL-DEFINE DEBUGALERT


/* In your test code you would just do the following: / / testing assertion */

DEF VAR h_ct AS INT NO-UNDO INIT 10.

{assert.i &CONDITION="h_ct = 8"}

DuStorm
+2  A: 

After some consideration here is my solution to the problem. It works based on the assumption that development environment propath is different from test and production environments and code is always re-compiled for test or production use:

&IF PROPATH MATCHES '*development*' &THEN 
&SCOPED-DEFINE ASSERTION   {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} ~
{11} {12} {13} {14} {15} {16} {17} {18} {19} {20} ~
{21} {22} {23} {24} {25} {26} {27} {28} {29} {30} ~
{31} {32} {33} {34} {35} {36} {37} {38} {39} {40} ~
{41} {42} {43} {44} {45} {46} {47} {48} {49} {50} ~
{51} {52} {53} {54} {55} {56} {57} {58} {59} {60} ~
{61} {62} {63} {64} {65} {66} {67} {68} {69} {70} ~
{71} {72} {73} {74} {75} {76} {77} {78} {79} {80} 


 IF NOT ({&ASSERTION}) THEN 
     MESSAGE "Failed assertion {&ASSERTION} in" PROGRAM-NAME(1).

 IF ({&ASSERTION}) = ? THEN 
     MESSAGE "Unknown value as a result of assertion {&ASSERTION} in" 
              PROGRAM-NAME(1).

&ENDIF

The code is designed to avoid any side effects and works equally well in any execution environment (GUI or ChUI, WebSpeed, AppServer, batch and so on).

1) Save the code as a file called “assert” (without any extension).

2) Place the file into a directory pointed to by PROPATH.

3) Sample usage:

{assert valid-handle(hProc)}
{assert i > 0 and i <= 100}
{assert cExtra begins ‘opt’}  /* note the single quotes */
{assert dtEnd > = dtStart}

As a variation it’s possible to avoid relying on propath altogether by having just an empty include file in test and production environment, the development version will become just:

&SCOPED-DEFINE ASSERTION   {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} ~
{11} {12} {13} {14} {15} {16} {17} {18} {19} {20} ~
{21} {22} {23} {24} {25} {26} {27} {28} {29} {30} ~
{31} {32} {33} {34} {35} {36} {37} {38} {39} {40} ~
{41} {42} {43} {44} {45} {46} {47} {48} {49} {50} ~
{51} {52} {53} {54} {55} {56} {57} {58} {59} {60} ~
{61} {62} {63} {64} {65} {66} {67} {68} {69} {70} ~
{71} {72} {73} {74} {75} {76} {77} {78} {79} {80} 


 IF NOT ({&ASSERTION}) THEN 
     MESSAGE "Failed assertion {&ASSERTION} in" PROGRAM-NAME(1).

 IF ({&ASSERTION}) = ? THEN 
     MESSAGE "Unknown value as a result of assertion {&ASSERTION} in" 
              PROGRAM-NAME(1).

An extra tip is to add an auto-text macro to your editor of choice that will automatically expand into {assert }.

Totophil