From b431e49cd7d2295e3a6f911a714155e4ebc316e0 Mon Sep 17 00:00:00 2001 From: JOEL IVEY Date: Tue, 7 Oct 2014 15:14:56 -0700 Subject: [PATCH] Individual routines %ut* These are the nine individual routines that are included in the KIDS and PackMan builds for the M-Unit functionality. --- Routines/%ut.m | 485 ++++++++++++++++++++++++++++++++++++++++++++ Routines/%ut1.m | 277 +++++++++++++++++++++++++ Routines/%utt1.m | 149 ++++++++++++++ Routines/%utt2.m | 12 ++ Routines/%utt3.m | 43 ++++ Routines/%utt4.m | 22 ++ Routines/%utt5.m | 123 +++++++++++ Routines/%utt6.m | 110 ++++++++++ Routines/%uttcovr.m | 46 +++++ 9 files changed, 1267 insertions(+) create mode 100644 Routines/%ut.m create mode 100644 Routines/%ut1.m create mode 100644 Routines/%utt1.m create mode 100644 Routines/%utt2.m create mode 100644 Routines/%utt3.m create mode 100644 Routines/%utt4.m create mode 100644 Routines/%utt5.m create mode 100644 Routines/%utt6.m create mode 100644 Routines/%uttcovr.m diff --git a/Routines/%ut.m b/Routines/%ut.m new file mode 100644 index 0000000..e659cfe --- /dev/null +++ b/Routines/%ut.m @@ -0,0 +1,485 @@ +%ut ;VEN-SMH/JLI - PRIMARY PROGRAM FOR M-UNIT TESTING ;08/24/14 21:45 + ;;0.1;MASH UTILITIES; + ; + ; This routine and its companion, %ut1, provide the basic functionality for + ; running unit tests on parts of M programs either at the command line level + ; or via the M-Unit GUI application for windows operating systems. + ; + ; Original by Dr. Joel Ivey + ; Contributions by Dr. Sam Habiel + ; + ; 100622 JLI - corrected typo in comments where %utINPT was listed as %utINP + ; 100622 JLI - removed a comment which indicated data could potentially be returned from the called routine + ; in the %utINPT array. + ; 100622 JLI - added code to handle STARTUP and SHUTDOWN from GUI app + ; 110719 JLI - modified separators in GUI handling from ^ to ~~^~~ + ; in the variable XTGUISEP if using a newer version of the + ; GUI app (otherwise, it is simply set to ^) since results + ; with a series of ^ embedded disturbed the output reported + ; 130726 SMH - Fixed SETUP and TEARDOWN so that they run before/after each + ; test rather than once. General refactoring. + ; 130726 SMH - SETUT initialized IO in case it's not there to $P. Inits vars + ; using DT^DICRW. + ; 131217 SMH - Change call in SETUP to S U="^" instead of DT^DICRW + ; 131218 SMH - Any checks to $ZE will also check $ZS for GT.M. + ; 131218 SMH - Remove calls to %ZISUTL to manage devices to prevent dependence on VISTA. + ; Use %utNIT("DEV","OLD") for old devices + ; 140109 SMH - Add parameter %utBREAK - Break upon error + ; 1402 SMH - Break will cause the break to happen even on failed tests. + ; 140401 SMH - Added Succeed entry point for take it into your hands tester. + ; 140401 SMH - Reformatted the output of M-Unit so that the test's name + ; will print BEFORE the execution of the test. This has been + ; really confusing for beginning users of M-Unit, so this was + ; necessary. + ; 140401 SMH - OK message gets printed at the end of --- as [OK]. + ; 140401 SMH - FAIL message now prints. Previously, OK failed to be printed. + ; Unfortunately, that's rather passive aggressive. Now it + ; explicitly says that a test failed. + ; 140503 SMH - Fixed IO issues all over the routine. Much simpler now. + ; 140731 JLI - Combined routine changes between JLI and SMH + ; Moved routines from %utNIT and %utNIT1 to %ut and %ut1 + ; Updated unit test routines (%utt1 to %utt6) + ; Created M-UNIT TEST GROUP file at 17.9001 based on the 17.9001 file + Q + ; +EN(%utRNAM,%utVERB,%utBREAK) ; .SR Entry point with primary test routine name, optional 1 for verbose output + N %utLIST,%utROU,%ut + I '+$G(%utVERB) S %utVERB=0 + S %utLIST=1,%utROU(%utLIST)=%utRNAM + D SETUT + D EN1(.%utROU,%utLIST) + Q + ; +SETUT ; + ; VEN/SMH 26JUL2013 + I '($D(IO)#2) S IO=$P + S U="^" + ; VEN/SMH 26JUL2013 END + ; + ; ZEXCEPT: %ut -- NEWED ON ENTRY + S %ut("IO")=IO + S %ut=1 ; set to identify unit test being run check with $$ISUTEST^%ut() + ; + ; ZEXCEPT: %utBREAK + I $G(%utBREAK) S %ut("BREAK")=1 + Q + ; +EN1(%utROU,%utLIST) ; + ; VEN/SMH 26JUL2013 - This block is refactored to fix problems with + ; SETUP and TEARDOWN not happening at the right time + N %utERRL,%utK,%utI,%utJ,%utSTRT + ; ZEXCEPT: %utVERB -- ARGUMENT TO EN + ; ZEXCEPT: %utGUI -- CONDITIONALLY DEFINED BY GUINEXT + ; ZEXCEPT: %ut -- NEWED IN EN + ; + ; Structure map for %ut + ; -- CURR = Counter for routine number. Used as sub in %utROU + ; -- ECNT = Entry point count in loop (cf. NERT); VEN/SMH - Needed? + ; -- FAIL = Number of failures + ; -- CHK = Number of checks ran (TF/EQ/FAIL) + ; -- NENT = Number of entry points ran + ; -- ERRN = Number of errors + S %ut("CURR")=0,%ut("ECNT")=0,%ut("FAIL")=0,%ut("CHK")=0,%ut("NENT")=0,%ut("ERRN")=0 + ; + ; -- GET LIST OF ROUTINES -- + ; first get any tree of routines from this one + D GETTREE^%ut1(.%utROU,.%utLIST) + ; + ; -- STARTUP -- + ; 070224 - following code added to allow one overall STARTUP code JLI + F S %ut("CURR")=%ut("CURR")+1 Q:'$D(%utROU(%ut("CURR"))) D I $G(%utSTRT)'="" D @%utSTRT Q + . I $T(@("STARTUP^"_%utROU(%ut("CURR"))))'="" S %utSTRT="STARTUP^"_%utROU(%ut("CURR")) + . Q + ; 070224 - end of addition JLI + ; + ; + ; Now process each routine that has been referenced + S %ut("CURR")=0 + F S %ut("CURR")=%ut("CURR")+1 Q:'$D(%utROU(%ut("CURR"))) D + . N %utETRY ; Test list to run + . ; + . ; Collect Test list. + . D CHEKTEST^%ut1(%utROU(%ut("CURR")),.%ut,.%utETRY) + . ; + . ; if a SETUP entry point exists, save it off in %ut + . N %utSETUP S %utSETUP="SETUP^"_%utROU(%ut("CURR")) + . S %ut("LINE")=$T(@%utSETUP) I %ut("LINE")'="" S %ut("SETUP")=%utSETUP + . K %utSETUP ; we're done! + . ; + . ; if a TEARDOWN entry point exists, ditto + . N %utTEARDOWN S %utTEARDOWN="TEARDOWN^"_%utROU(%ut("CURR")) + . S %ut("LINE")=$T(@%utTEARDOWN) I %ut("LINE")'="" S %ut("TEARDOWN")=%utTEARDOWN + . K %utTEARDOWN ; done here. + . ; + . ; VEN/SMH 26JUL2013 - this block changed to correct running of setup and teardown + . ; run each of the specified entry points + . ; + . ; == THIS FOR/DO BLOCK IS THE CENTRAL TEST RUNNER == + . S %utI=0 + . F S %utI=$O(%utETRY(%utI)) Q:%utI'>0 S %ut("ENUM")=%ut("ERRN")+%ut("FAIL") D + . . N $ETRAP S $ETRAP="D ERROR^%ut" + . . ; + . . ; Run Set-up Code (only if present) + . . S %ut("ENT")=$G(%ut("SETUP")) ; Current entry + . . S %ut("NAME")="Set-up Code" + . . D:%ut("ENT")]"" @%ut("ENT") + . . ; + . . ; Run actual test + . . S %ut("ECNT")=%ut("ECNT")+1 + . . S %ut("NAME")=%utETRY(%utI,"NAME") + . . S %ut("ENT")=%utETRY(%utI)_"^"_%utROU(%ut("CURR")) + . . I %utVERB,'$D(%utGUI) D VERBOSE1(.%utETRY,%utI) ; Say what we executed. + . . D @%ut("ENT") + . . ; + . . ; Run Teardown Code (only if present) + . . S %ut("ENT")=$G(%ut("TEARDOWN")) + . . S %ut("NAME")="Teardown Code" + . . D:%ut("ENT")]"" @%ut("ENT") + . . ; + . . ; ENUM = Number of errors + failures + . . ; Only print out the success message [OK] If our error number remains + . . ; the same as when we started the loop. + . . I %utVERB,'$D(%utGUI) D + . . . I %ut("ENUM")=(%ut("ERRN")+%ut("FAIL")) D VERBOSE(.%utETRY,%utI,1) I 1 + . . . E D VERBOSE(.%utETRY,%utI,0) + . ; + . ; + . ; keep a %utCNT of number of entry points executed across all routines + . S %ut("NENT")=%ut("NENT")+%ut("ENTN") + . Q + ; + ; -- SHUTDOWN -- + ; 070224 - following code added to allow one overall SHUTDOWN code JLI + N XTFINISH + S %ut("CURR")=0 + F S %ut("CURR")=%ut("CURR")+1 Q:'$D(%utROU(%ut("CURR"))) D I $G(XTFINISH)'="" D @XTFINISH Q + . I $T(@("SHUTDOWN^"_%utROU(%ut("CURR"))))'="" S XTFINISH="SHUTDOWN^"_%utROU(%ut("CURR")) + . Q + ; 070224 - End of addition JLI + ; and output the results + D SETIO + W !!,"Ran ",%utLIST," Routine",$S(%utLIST>1:"s",1:""),", ",%ut("NENT")," Entry Tag",$S(%ut("NENT")>1:"s",1:"") + W !,"Checked ",%ut("CHK")," test",$S(%ut("CHK")>1:"s",1:""),", with ",%ut("FAIL")," failure",$S(%ut("FAIL")'=1:"s",1:"")," and encountered ",%ut("ERRN")," error",$S(%ut("ERRN")'=1:"s",1:""),"." + D RESETIO + Q + ; -- end EN1 +VERBOSE(%utETRY,%utI,SUCCESS) ; Say whether we succeeded or failed. + ; ZEXCEPT: %ut - NEWED IN EN + D SETIO + N I F I=$X+3:1:73 W "-" + W ?73 + I $G(SUCCESS) W "[OK]" + E W "[FAIL]" + D RESETIO + Q + ; +VERBOSE1(%utETRY,%utI) ; Print out the entry point info + ; ZEXCEPT: %ut - NEWED IN EN + D SETIO + W !,%utETRY(%utI) I $G(%utETRY(%utI,"NAME"))'="" W " - ",%utETRY(%utI,"NAME") + D RESETIO + Q +CHKTF(XTSTVAL,XTERMSG) ; Entry point for checking True or False values + ; ZEXCEPT: %utERRL,%utGUI - CREATED IN SETUP, KILLED IN END + ; ZEXCEPT: %ut - NEWED IN EN + ; ZEXCEPT: XTGUISEP - newed in GUINEXT + I '$D(XTSTVAL) D NVLDARG Q + I $G(XTERMSG)="" S XTERMSG="no failure message provided" + S %ut("CHK")=$G(%ut("CHK"))+1 + I '$D(%utGUI) D + . D SETIO + . I 'XTSTVAL W !,%ut("ENT")," - " W:%ut("NAME")'="" %ut("NAME")," - " D + . . W XTERMSG,! S %ut("FAIL")=%ut("FAIL")+1,%utERRL(%ut("FAIL"))=%ut("NAME"),%utERRL(%ut("FAIL"),"MSG")=XTERMSG,%utERRL(%ut("FAIL"),"ENTRY")=%ut("ENT") + . . I $D(%ut("BREAK")) BREAK ; Break upon failure + . . Q + . I XTSTVAL W "." + . D RESETIO + . Q + I $D(%utGUI),'XTSTVAL S %ut("CNT")=%ut("CNT")+1,@%ut("RSLT")@(%ut("CNT"))=%ut("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_XTERMSG + Q + ; +CHKEQ(XTEXPECT,XTACTUAL,XTERMSG) ; Entry point for checking values to see if they are EQUAL + N FAILMSG + ; ZEXCEPT: %utERRL,%utGUI -CREATED IN SETUP, KILLED IN END + ; ZEXCEPT: %ut -- NEWED IN EN + ; ZEXCEPT: XTGUISEP - newed in GUINEXT + I '$D(XTEXPECT)!'$D(XTACTUAL) D NVLDARG Q ; JLI 140824 changed from AND to OR, since both necessary, but only one might be entered + S XTACTUAL=$G(XTACTUAL),XTEXPECT=$G(XTEXPECT) + I $G(XTERMSG)="" S XTERMSG="no failure message provided" + S %ut("CHK")=%ut("CHK")+1 + I XTEXPECT'=XTACTUAL S FAILMSG="<"_XTEXPECT_"> vs <"_XTACTUAL_"> - " + I '$D(%utGUI) D + . D SETIO + . I XTEXPECT'=XTACTUAL W !,%ut("ENT")," - " W:%ut("NAME")'="" %ut("NAME")," - " W FAILMSG,XTERMSG,! D + . . S %ut("FAIL")=%ut("FAIL")+1,%utERRL(%ut("FAIL"))=%ut("NAME"),%utERRL(%ut("FAIL"),"MSG")=XTERMSG,%utERRL(%ut("FAIL"),"ENTRY")=%ut("ENT") + . . I $D(%ut("BREAK")) BREAK ; Break upon failure + . . Q + . E W "." + . D RESETIO + . Q + I $D(%utGUI),XTEXPECT'=XTACTUAL S %ut("CNT")=%ut("CNT")+1,@%ut("RSLT")@(%ut("CNT"))=%ut("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_FAILMSG_XTERMSG + Q + ; +FAIL(XTERMSG) ; Entry point for generating a failure message + ; ZEXCEPT: %utERRL,%utGUI -CREATED IN SETUP, KILLED IN END + ; ZEXCEPT: %ut -- NEWED ON ENTRY + ; ZEXCEPT: XTGUISEP - newed in GUINEXT + I $G(XTERMSG)="" S XTERMSG="no failure message provided" + S %ut("CHK")=%ut("CHK")+1 + I '$D(%utGUI) D + . D SETIO + . W !,%ut("ENT")," - " W:%ut("NAME")'="" %ut("NAME")," - " W XTERMSG,! D + . . S %ut("FAIL")=%ut("FAIL")+1,%utERRL(%ut("FAIL"))=%ut("NAME"),%utERRL(%ut("FAIL"),"MSG")=XTERMSG,%utERRL(%ut("FAIL"),"ENTRY")=%ut("ENT") + . . I $D(%ut("BREAK")) BREAK ; Break upon failure + . . Q + . D RESETIO + . Q + I $D(%utGUI) S %ut("CNT")=%ut("CNT")+1,@%ut("RSLT")@(%ut("CNT"))=%ut("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_XTERMSG + Q +SUCCEED ; Entry point for forcing a success (Thx David Whitten) + ; ZEXCEPT: %utERRL,%utGUI - CREATED IN SETUP, KILLED IN END + ; ZEXCEPT: %ut - NEWED IN EN + ; Switch IO and write out the dot for activity + I '$D(%utGUI) D + . D SETIO + . W "." + . D RESETIO + ; + ; Increment test counter + S %ut("CHK")=%ut("CHK")+1 + QUIT + ; +CHKLEAKS(%utCODE,%utLOC,%utINPT) ; functionality to check for variable leaks on executing a section of code + ; %utCODE - A string that specifies the code that is to be XECUTED and checked for leaks. + ; this should be a complete piece of code (e.g., "S X=$$NOW^XLFDT()" or "D EN^%ut(""ROUNAME"")") + ; %utLOC - A string that is used to indicate the code tested for variable leaks + ; %utINPT - An optional variable which may be passed by reference. This may + ; be used to pass any variable values, etc. into the code to be + ; XECUTED. In this case, set the subscript to the variable name and the + ; value of the subscripted variable to the desired value of the subscript. + ; e.g., (using NAME as my current namespace) + ; S CODE="S %utINPT=$$ENTRY^ROUTINE(ZZVALUE1,ZZVALUE2)" + ; S NAMELOC="ENTRY^ROUTINE leak test" (or simply "ENTRY^ROUTINE") + ; S NAMEINPT("ZZVALUE1")=ZZVALUE1 + ; S NAMEINPT("ZZVALUE2")=ZZVALUE2 + ; D CHKLEAKS^%ut(CODE,NAMELOC,.NAMEINPT) + ; + ; If part of a unit test, any leaked variables in ENTRY^ROUTINE which result + ; from running the code with the variables indicated will be shown as FAILUREs. + ; + ; If called outside of a unit test, any leaked variables will be printed to the + ; current device. + ; + N (%utCODE,%utLOC,%utINPT,DUZ,IO,U,%utERRL,%ut,%utGUI,%utI,%utJ,%utK,%utLIST,%utROU,%utSTRT) + ; ZEXCEPT: %ut - part of exclusive NEW TESTS FOR EXISTENCE ONLY + ; ZEXCEPT: %utVAR - handled by exclusive NEW + ; + ; ACTIVATE ANY VARIABLES PASSED AS SUBSCRIPTS TO %utINPT TO THEIR VALUES + S %utVAR=" " F S %utVAR=$O(%utINPT(%utVAR)) Q:%utVAR="" S (@%utVAR)=%utINPT(%utVAR) + X %utCODE + N ZZUTVAR S ZZUTVAR="%" + I $G(%ut)=1 D + . I $D(@ZZUTVAR),'$D(%utINPT(ZZUTVAR)) D FAIL^%ut(%utLOC_" VARIABLE LEAK: "_ZZUTVAR) + . F S ZZUTVAR=$O(@ZZUTVAR) Q:ZZUTVAR="" I $E(ZZUTVAR,1,3)'="%ut",'$D(%utINPT(ZZUTVAR)),",DUZ,IO,U,DTIME,ZZUTVAR,DT,%ut,"'[(","_ZZUTVAR_",") D FAIL^%ut(%utLOC_" VARIABLE LEAK: "_ZZUTVAR) + . Q + I '($G(%ut)=1) D + . I $D(@ZZUTVAR),'$D(%utINPT(ZZUTVAR)) W !,%utLOC_" VARIABLE LEAK: "_ZZUTVAR + . F S ZZUTVAR=$O(@ZZUTVAR) Q:ZZUTVAR="" I $E(ZZUTVAR,1,3)'="%ut",'$D(%utINPT(ZZUTVAR)),",DUZ,IO,U,DTIME,ZZUTVAR,DT,%ut,"'[(","_ZZUTVAR_",") W !,%utLOC_" VARIABLE LEAK: "_ZZUTVAR + . Q + Q + ; +NVLDARG ; generate message for invalid arguments to test + N XTERMSG + ; ZEXCEPT: %ut -- NEWED ON ENTRY + ; ZEXCEPT: %utERRL,%utGUI -CREATED IN SETUP, KILLED IN END + ; ZEXCEPT: XTGUISEP - newed in GUINEXT + S XTERMSG="NO VALUES INPUT TO CHKEQ^%ut - no evaluation possible" + I '$D(%utGUI) D + . D SETIO + . W !,%ut("ENT")," - " W:%ut("NAME")'="" %ut("NAME")," - " W XTERMSG,! D + . . S %ut("FAIL")=%ut("FAIL")+1,%utERRL(%ut("FAIL"))=%ut("NAME"),%utERRL(%ut("FAIL"),"MSG")=XTERMSG,%utERRL(%ut("FAIL"),"ENTRY")=%ut("ENT") + . . Q + . D RESETIO + . Q + I $D(%utGUI) S %ut("CNT")=%ut("CNT")+1,@%ut("RSLT")@(%ut("CNT"))=%ut("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_XTERMSG + Q + ; +ERROR ; record errors + ; ZEXCEPT: %utERRL,%utGUI,%utERR -CREATED IN SETUP, KILLED IN END + ; ZEXCEPT: %ut -- NEWED ON ENTRY + ; ZEXCEPT: XTGUISEP - newed in GUINEXT + S %ut("CHK")=%ut("CHK")+1 + I '$D(%utGUI) D ERROR1 + I $D(%utGUI) D + . S %ut("CNT")=%ut("CNT")+1 + . S %utERR=%utERR+1 + . S @%ut("RSLT")@(%ut("CNT"))=%ut("LOC")_XTGUISEP_"ERROR"_XTGUISEP_$S(+$SY=47:$ZS,1:$ZE) + . Q + S @($S(+$SY=47:"$ZS",1:"$ZE")_"="_""""""),$EC="" + Q + ; +ERROR1 ; + I $G(%ut("BREAK")) BREAK ; if we are asked to break upon error, please do so! + ; ZEXCEPT: %utERRL -CREATED IN SETUP, KILLED IN END + ; ZEXCEPT: %ut -- NEWED ON ENTRY + D SETIO + W !,%ut("ENT")," - " W:%ut("NAME")'="" %ut("NAME")," - Error: " W $S(+$SY=47:$ZS,1:$ZE),! D + . S %ut("ERRN")=%ut("ERRN")+1,%utERRL(%ut("ERRN"))=%ut("NAME"),%utERRL(%ut("FAIL"),"MSG")=$S(+$SY=47:$ZS,1:$ZE),%utERRL(%ut("FAIL"),"ENTRY")=%ut("ENT") + . Q + D RESETIO + Q +SETIO ; Set M-Unit Device to write the results to... + ; ZEXCEPT: %ut -- NEWED ON ENTRY + I $IO'=%ut("IO") S (IO(0),%ut("DEV","OLD"))=$IO USE %ut("IO") SET IO=$IO + QUIT + ; +RESETIO ; Reset $IO back to the original device if we changed it. + ; ZEXCEPT: %ut -- NEWED ON ENTRY + I $D(%ut("DEV","OLD")) S IO(0)=%ut("IO") U %ut("DEV","OLD") S IO=$IO K %ut("DEV","OLD") + QUIT + ; +ISUTEST() ; .SUPPORTED API TO DETERMINE IF CURRENTLY IN UNIT TEST + ; ZEXCEPT: %ut -- NEWED ON ENTRY + Q $G(%ut)=1 + ; +PICKSET ; .OPT Interactive selection of MUnit Test Group + N DIC,Y,%utROU,%utLIST,DIR + S DIC=17.9001,DIC(0)="AEQM" D ^DIC Q:Y'>0 W ! + D GETSET(+Y,.%utROU,.%utLIST) + N DIC,Y,%ut + D SETUT + D EN1(.%utROU,%utLIST) + S DIR(0)="EA",DIR("A")="Enter RETURN to continue:" D ^DIR K DIR + Q + ; +RUNSET(SETNAME,VERBOSE) ; .SR Run with Specified Selection of MUnit Test Group + N Y,%utROU,%utLIST,%utVERB + Q:$G(SETNAME)="" + S %utVERB=$G(VERBOSE,0) + S Y=+$$FIND1^DIC(17.9001,"","X",SETNAME) Q:Y'>0 + D GETSET(Y,.%utROU,.%utLIST) + N Y,SETNAME,%ut + D SETUT + D EN1(.%utROU,%utLIST) + Q + ; + ; DOSET CAN BE USED TO RUN A SET OF TESTS BASED ON THE IEN IN THE MUNIT TEST GROUP file (#17.9001) +DOSET(IEN,%utVERB) ; 140731 JLI added %utVERB as a second argument + ; IEN - Internal entry number for selected set of tests in the MUNIT TEST GROUP file (#17.9001) + ; %utVERB - optional input that indicates verbose output is permitted + ; + N %utROU,%utLIST + I '$D(%utVERB) S %utVERB=0 + S %utLIST=0 + D GETSET($G(IEN),.%utROU,.%utLIST) + I %utLIST>0 N IEN,%ut D SETUT,EN1(.%utROU,%utLIST) + Q + ; +GETSET(IEN,%utROU,%utLIST) ; JLI 140731 - called from PICKSET, RUNSET, DOSET, GUISET + N IENS,%utROOT + S IENS=IEN_"," D GETS^DIQ(17.9001,IENS,"1*","","%utROOT") + S %utLIST=0,IENS="" F S IENS=$O(%utROOT(17.90011,IENS)) Q:IENS="" S %utLIST=%utLIST+1,%utROU(%utLIST)=%utROOT(17.90011,IENS,.01) + Q + ; +GUISET(%utRSLT,XTSET) ; Entry point for GUI start with selected Test Set IEN - called by %ut-TEST GROUP LOAD rpc + N %utROU,%utLIST,%ut + D SETUT + S %ut("RSLT")=$NA(^TMP("MUNIT-%utRSLT",$J)) K @%ut("RSLT") + D GETSET(XTSET,.%utROU,.%utLIST) + D GETLIST(.%utROU,%utLIST,%ut("RSLT")) + S @%ut("RSLT")@(1)=(@%ut("RSLT")@(1))_"^1" ; 110719 mark as new version + S %utRSLT=%ut("RSLT") + Q + ; +GUILOAD(%utRSLT,%utROUN) ; Entry point for GUI start with %utROUN containing primary routine name - called by %ut-TEST LOAD rpc + N %utROU,%ut + D SETUT + S %ut("RSLT")=$NA(^TMP("MUNIT-%utRSLT",$J)) K @%ut("RSLT") + S %utROU(1)=%utROUN + D GETLIST(.%utROU,1,%ut("RSLT")) + S @%ut("RSLT")@(1)=(@%ut("RSLT")@(1))_"^1" ; 110719 mark as new version + S %utRSLT=%ut("RSLT") + Q + ; +GETLIST(%utROU,%utLIST,%utRSLT) ; called from GUISET, GUILOAD + N I,%utROUL,%utROUN,%ut,XTCOMNT,XTVALUE,%utCNT + S XTVALUE=$NA(^TMP("GUI-MUNIT",$J)) K @XTVALUE + S %utCNT=0,XTCOMNT="" + D GETTREE^%ut1(.%utROU,%utLIST) + F I=1:1 Q:'$D(%utROU(I)) S %utROUL(%utROU(I))="" + S %utROUN="" F S %utROUN=$O(%utROUL(%utROUN)) Q:%utROUN="" D LOAD(%utROUN,.%utCNT,XTVALUE,XTCOMNT,.%utROUL) + M @%utRSLT=@XTVALUE + K @%utRSLT@("SHUTDOWN") + K @%utRSLT@("STARTUP") + S @XTVALUE@("LASTROU")="" ; Use this to keep track of place in routines + Q + ; + ; generate list of unit test routines, entry points and comments on test for entry point +LOAD(%utROUN,%utNCNT,XTVALUE,XTCOMNT,%utROUL) ; called from GETLIST, and recursively from LOAD + I $T(@("^"_%utROUN))="" S %utNCNT=%utNCNT+1,@XTVALUE@(%utNCNT)=%utROUN_"^^*** ERROR - ROUTINE NAME NOT FOUND" Q + S %utNCNT=%utNCNT+1,@XTVALUE@(%utNCNT)=%utROUN_U_U_XTCOMNT + ;N %utI,XTX1,XTX2,LINE + N %utI,XTX1,XTX2,LINE,LIST,I + ; 100622 JLI added code to identify STARTUP and TEARDOWN + I $T(@("STARTUP^"_%utROUN))'="",'$D(@XTVALUE@("STARTUP")) S @XTVALUE@("STARTUP")="STARTUP^"_%utROUN + I $T(@("SHUTDOWN^"_%utROUN))'="",'$D(@XTVALUE@("SHUTDOWN")) S @XTVALUE@("SHUTDOWN")="SHUTDOWN^"_%utROUN + ; JLI 140731 handle @TEST identified test tags + D NEWSTYLE^%ut1(.LIST,%utROUN) + F I=1:1:LIST S %utNCNT=%utNCNT+1,@XTVALUE@(%utNCNT)=%utROUN_U_LIST(I) + ; JLI 140731 end of @TEST addition + F %utI=1:1 S LINE=$T(@("XTENT+"_%utI_"^"_%utROUN)) S XTX1=$P(LINE,";",3) Q:XTX1="" S XTX2=$P(LINE,";",4),%utNCNT=%utNCNT+1,@XTVALUE@(%utNCNT)=%utROUN_U_XTX1_U_XTX2 + F %utI=1:1 S LINE=$T(@("XTROU+"_%utI_"^"_%utROUN)) S XTX1=$P(LINE,";",3) Q:XTX1="" S XTCOMNT=$P(LINE,";",4) I '$D(%utROUL(XTX1)) S %utROUL(XTX1)="" D LOAD(XTX1,.%utNCNT,XTVALUE,XTCOMNT,.%utROUL) + Q + ; +GUINEXT(%utRSLT,%utLOC,XTGUISEP) ; Entry point for GUI execute next test - called by %ut-TEST NEXT rpc + ; XTGUISEP - added 110719 to provide for changing separator for GUI + ; return from ^ to another value ~~^~~ so that data returned + ; is not affected by ^ values in the data - if not present + ; sets value to default ^ + N %utETRY,%utROUT,XTOLROU,XTVALUE,%utERR,%utGUI + N %ut + I $G(XTGUISEP)="" S XTGUISEP="^" + D SETUT + S %ut("LOC")=%utLOC + S %ut("CURR")=0,%ut("ECNT")=0,%ut("FAIL")=0,%ut("CHK")=0,%ut("NENT")=0,%ut("ERRN")=0 + S XTVALUE=$NA(^TMP("GUI-MUNIT",$J)) + S %ut("RSLT")=$NA(^TMP("GUINEXT",$J)) K @%ut("RSLT") + S %utRSLT=%ut("RSLT") + S %utETRY=$P(%utLOC,U),%utROUT=$P(%utLOC,U,2),XTOLROU=$G(@XTVALUE@("LASTROU")) + S %utGUI=1 + ; I %utROUT'=XTOLROU D I %utROUT="" S @%utRSLT@(1)="" K @XTVALUE Q ;140731 JLI - commented out + D I %utROUT="" S @%utRSLT@(1)="" K @XTVALUE Q ; 140731 JLI - replaced previous line - moves check for SHUTDOWN at end of processing + . I XTOLROU="",$D(@XTVALUE@("STARTUP")) D + . . S %ut("LOC")=@XTVALUE@("STARTUP") + . . N $ETRAP S $ETRAP="D ERROR^%ut" + . . D @(@XTVALUE@("STARTUP")) + . . Q + . S @XTVALUE@("LASTROU")=%utROUT I %utROUT'="",$T(@("SETUP^"_%utROUT))'="" D + . . S %ut("LOC")="SETUP^"_%utROUT + . . N $ETRAP S $ETRAP="D ERROR^%ut" + . . D @("SETUP^"_%utROUT) + . . Q + . I %utROUT="",$D(@XTVALUE@("SHUTDOWN")) D + . . S %ut("LOC")=@XTVALUE@("SHUTDOWN") + . . N $ETRAP S $ETRAP="D ERROR^%ut" + . . D @(@XTVALUE@("SHUTDOWN")) + . . Q + . Q + S %ut("LOC")=%utLOC + S %ut("CHK")=0,%ut("CNT")=1,%utERR=0 + D ; to limit range of error trap so we continue through other tests + . N $ETRAP S $ETRAP="D ERROR^%ut" + . D @%ut("LOC") + . Q + I $T(@("TEARDOWN^"_%utROUT))'="" D + . S %ut("LOC")="TEARDOWN^"_%utROUT + . N $ETRAP S $ETRAP="D ERROR^%ut" + . D @("TEARDOWN^"_%utROUT) + . Q + S @%ut("RSLT")@(1)=%ut("CHK")_XTGUISEP_(%ut("CNT")-1-%utERR)_XTGUISEP_%utERR + Q + ; +TESTCOVR ; entry under coverage analysis + D ENTRY^%uttcovr ; does analysis while running various unit tests + Q + ; diff --git a/Routines/%ut1.m b/Routines/%ut1.m new file mode 100644 index 0000000..6559fb1 --- /dev/null +++ b/Routines/%ut1.m @@ -0,0 +1,277 @@ +%ut1 ;VEN/SMH/JLI - CONTINUATION OF M-UNIT PROCESSING ;2014-09-10 7:41 PM + ;;0.1;MASH UTILITIES; + ; + ;following is original header from XTMUNIT1 in unreleased patch XT*7.3*81 VA code + ;XTMUNIT1 ;JLI/FO-OAK-CONTINUATION OF UNIT TEST ROUTINE ;2014-04-17 5:26 PM + ;;7.3;TOOLKIT;**81**;APR 25 1995;Build 24 + ; + ; + ; Original by Dr. Joel Ivey + ; Major contributions by Dr. Sam Habiel + ; + ; Changes: + ; 130726 SMH - Moved test collection logic from %utUNIT to here (multiple places) + ; 131218 SMH - dependence on XLFSTR removed + ; 131218 SMH - CHEKTEST refactored to use $TEXT instead of ^%ZOSF("LOAD") + ; 131218 SMH - CATCHERR now nulls out $ZS if on GT.M + ; + ; TODO: find this routine and add to repo. + D EN^%ut("%utt3") + Q + ; +CHEKTEST(%utROU,%ut,%utUETRY) ; Collect Test list. + ; %utROU - input - Name of routine to check for tags with @TEST attribute + ; %ut - input/output - passed by reference + ; %utUETRY - input/output - passed by reference + ; + ; Test list collected in two ways: + ; - @TEST on labellines + ; - Offsets of XTENT + ; + S %ut("ENTN")=0 ; Number of test, sub to %utUETRY. + ; + ; This stanza and everything below is for collecting @TEST. + ; VEN/SMH - block refactored to use $TEXT instead of ^%ZOSF("LOAD") + N I,LIST + S I=$L($T(@(U_%utROU))) I I<0 Q "-1^Invalid Routine Name" + N $ETRAP S $ETRAP="D CATCHERR^%ut1" + ; 140731 JLI - the following SMH code is replaced by the code below + ; Complexity galore: $TEXT loops through routine + ; IF tab or space isn't the first character ($C(9,32)) and line contains @TEST + ; Load that line as a testing entry point + ; F I=1:1 S LINE=$T(@("+"_I_U_%utROU)) Q:LINE="" I $C(9,32)'[$E(LINE),$$UP(LINE)["@TEST" D + ; . N TAGNAME,CHAR,NPAREN S TAGNAME="",NPAREN=0 + ; . F Q:LINE="" S CHAR=$E(LINE),LINE=$E(LINE,2,999) Q:CHAR="" Q:" ("[CHAR S TAGNAME=TAGNAME_CHAR + ; . ; should be no paren or arguments + ; . I CHAR="(" Q + ; . F Q:LINE="" S CHAR=$E(LINE) Q:" ;"'[CHAR S LINE=$E(LINE,2,999) + ; . I $$UP($E(LINE,1,5))="@TEST" S LINE=$E(LINE,6,999) D + ; . . S %ut("ENTN")=%ut("ENTN")+1,%utUETRY(%ut("ENTN"))=TAGNAME + ; . . F Q:LINE="" S CHAR=$E(LINE) Q:CHAR?1AN S LINE=$E(LINE,2,999) + ; . . S %utUETRY(%ut("ENTN"),"NAME")=LINE + ; JLI 140731 - end of code replaced by following code + ; JLI 140731 - the following code replaces the code above + D NEWSTYLE(.LIST,%utROU) + F I=1:1:LIST S %ut("ENTN")=%ut("ENTN")+1,%utUETRY(%ut("ENTN"))=$P(LIST(I),U),%utUETRY(%ut("ENTN"),"NAME")=$P(LIST(I),U,2,99) + ; JLI 140731 - end of replacement code + ; + ; + ; This Stanza is to collect XTENT offsets + N %utUI F %utUI=1:1 S %ut("ELIN")=$T(@("XTENT+"_%utUI_"^"_%utROU)) Q:$P(%ut("ELIN"),";",3)="" D + . S %ut("ENTN")=%ut("ENTN")+1,%utUETRY(%ut("ENTN"))=$P(%ut("ELIN"),";",3),%utUETRY(%ut("ENTN"),"NAME")=$P(%ut("ELIN"),";",4) + . Q + ; + QUIT + ; + ; VEN/SMH - Is this catch needed anymore? +CATCHERR ; catch error on trying to load file if it doesn't exist ; JLI 120806 + W !,"In CATCHERR",! ; JLI 140910 DEBUG + S $ZE="",$EC="" + I +$SY=47 S $ZS="" ; VEN/SMH fur GT.M. + QUIT + ; + ; VEN/SMH 26JUL2013 - Moved GETTREE here. +GETTREE(%utROU,%utULIST) ; + ; first get any other routines this one references for running subsequently + ; then any that they refer to as well + ; this builds a tree of all routines referred to by any routine including each only once + N %utUK,%utUI,%utUJ,%utURNAM,%utURLIN + F %utUK=1:1 Q:'$D(%utROU(%utUK)) D + . F %utUI=1:1 S %utURLIN=$T(@("XTROU+"_%utUI_"^"_%utROU(%utUK))) S %utURNAM=$P(%utURLIN,";",3) Q:%utURNAM="" D + . . F %utUJ=1:1:%utULIST I %utROU(%utUJ)=%utURNAM S %utURNAM="" Q + . . I %utURNAM'="",$T(@("+1^"_%utURNAM))="" W:'$D(XWBOS) "Referenced routine ",%utURNAM," not found.",! Q + . . S:%utURNAM'="" %utULIST=%utULIST+1,%utROU(%utULIST)=%utURNAM + QUIT + ; +NEWSTYLE(LIST,ROUNAME) ; JLI 140726 identify and return list of newstyle tags or entries for this routine + ; LIST - input, passed by reference - returns containing array with list of tags identified as tests + ; LIST indicates number of tags identified, LIST(n)=tag^test_info where tag is entry point for test + ; ROUNAME - input - routine name in which tests should be identified + ; + N I,VALUE,LINE + K LIST S LIST=0 + ; search routine by line for a tag and @TEST declaration + F I=1:1 S LINE=$T(@("+"_I_"^"_ROUNAME)) Q:LINE="" S VALUE=$$CHECKTAG(LINE) I VALUE'="" S LIST=LIST+1,LIST(LIST)=VALUE + Q + ; +CHECKTAG(LINE) ; JLI 140726 check line to determine @test TAG + ; LINE - input - Line of code to be checked + ; returns null line if not @TEST line, otherwise TAG^NOTE + N TAG,NOTE,CHAR + I $E(LINE)=" " Q "" ; test entry must have a tag + I $$UP(LINE)'["@TEST" Q "" ; must have @TEST declaration + I $P($$UP(LINE),"@TEST")["(" Q "" ; can't have an argument + S TAG=$P(LINE," "),LINE=$P(LINE," ",2,400),NOTE=$P($$UP(LINE),"@TEST"),LINE=$E(LINE,$L(NOTE)+5+1,$L(LINE)) + F Q:NOTE="" S CHAR=$E(NOTE),NOTE=$E(NOTE,2,$L(NOTE)) I " ;"'[CHAR Q ; + I $L(NOTE)'=0 Q "" ; @TEST must be first text on line + F Q:$E(LINE)'=" " S LINE=$E(LINE,2,$L(LINE)) ; remove leading spaces from test info + S TAG=TAG_U_LINE + Q TAG + ; + ; VEN/SMH 17DEC2013 - Remove dependence on VISTA - Uppercase here instead of XLFSTR. +UP(X) ; + Q $TR(X,"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ") + ; +COV(NMSP,COVCODE,VERBOSITY) ; VEN/SMH - PUBLIC ENTRY POINT; Coverage calculations + ; NMSP: Namespace of the routines to analyze. End with * to include all routines. + ; Not using * will only include the routine with NMSP name. + ; e.g. PSOM* will include all routines starting with PSOM + ; PSOM will only include PSOM. + ; COVCODE: Mumps code to run over which coverage will be calculated. Typically Unit Tests. + ; VERBOSITY (optional): Scalar from -1 to 3. + ; - -1 = Global output in ^TMP("%utCOVREPORT",$J) + ; - 0 = Print only total coverage + ; - 1 = Break down by routine + ; - 2 = Break down by routine and tag + ; - 3 = Break down by routine and tag, and print lines that didn't execute for each tag. + ; + Q:'(+$SY=47) ; GT.M only! + ; + ; ZEXCEPT: CTRAP - not really a variable + S VERBOSITY=+$G(VERBOSITY) ; Get 0 if not passed. + N %ZR ; GT.M specific + D SILENT^%RSEL(NMSP,"SRC") ; GT.M specific. On Cache use $O(^$R(RTN)). + ; + N RN S RN="" + W "Loading routines to test coverage...",! + F S RN=$O(%ZR(RN)) Q:RN="" W RN," " D + . N L2 S L2=$T(+2^@RN) + . S L2=$TR(L2,$C(9,32)) ; Translate spaces and tabs out + . I $E(L2,1,2)'=";;" K %ZR(RN) ; Not a human produced routine + ; + N RTNS M RTNS=%ZR + K %ZR + ; + N GL + S GL=$NA(^TMP("%utCOVCOHORT",$J)) + K @GL + D RTNANAL(.RTNS,GL) + K ^TMP("%utCOVCOHORTSAV",$J) + M ^TMP("%utCOVCOHORTSAV",$J)=^TMP("%utCOVCOHORT",$J) + ; + ; + K ^TMP("%utCOVRESULT",$J) + VIEW "TRACE":1:$NA(^TMP("%utCOVRESULT",$J)) ; GT.M START PROFILING + DO ; Run the code, but keep our variables to ourselves. + . NEW $ETRAP,$ESTACK + . SET $ETRAP="Q:($ES&$Q) -9 Q:$ES W ""CTRL-C ENTERED""" + . USE $PRINCIPAL:(CTRAP=$C(3)) + . NEW (DUZ,IO,COVCODE,U,DILOCKTM,DISYS,DT,DTIME,IOBS,IOF,IOM,ION,IOS,IOSL,IOST,IOT,IOXY) + . XECUTE COVCODE + VIEW "TRACE":0:$NA(^TMP("%utCOVRESULT",$J)) ; GT.M STOP PROFILING + ; + D COVCOV($NA(^TMP("%utCOVCOHORT",$J)),$NA(^TMP("%utCOVRESULT",$J))) ; Venn diagram matching between globals + ; + ; Report + I VERBOSITY=-1 D + . K ^TMP("%utCOVREPORT",$J) + . D COVRPTGL($NA(^TMP("%utCOVCOHORTSAV",$J)),$NA(^TMP("%utCOVCOHORT",$J)),$NA(^TMP("%utCOVRESULT",$J)),$NA(^TMP("%utCOVREPORT",$J))) + E D COVRPT($NA(^TMP("%utCOVCOHORTSAV",$J)),$NA(^TMP("%utCOVCOHORT",$J)),$NA(^TMP("%utCOVRESULT",$J)),VERBOSITY) + ; + QUIT + ; +RTNANAL(RTNS,GL) ; [Private] - Routine Analysis + ; Create a global similar to the trace global produced by GT.M in GL + ; Only non-comment lines are stored. + ; A tag is always stored. Tag,0 is stored only if there is code on the tag line (format list or actual code). + ; tags by themselves don't count toward the total. + ; + N RTN S RTN="" + F S RTN=$O(RTNS(RTN)) Q:RTN="" D ; for each routine + . N TAG + . S TAG=RTN ; start the tags at the first + . N I,LN F I=2:1 S LN=$T(@TAG+I^@RTN) Q:LN="" D ; for each line, starting with the 3rd line (2 off the first tag) + . . I $E(LN)?1A D QUIT ; formal line + . . . N T ; Terminator + . . . N J F J=1:1:$L(LN) S T=$E(LN,J) Q:T'?1AN ; Loop to... + . . . S TAG=$E(LN,1,J-1) ; Get tag + . . . S @GL@(RTN,TAG)=TAG ; store line + . . . I T="(" S @GL@(RTN,TAG,0)=LN ; formal list + . . . E D ; No formal list + . . . . N LNTR S LNTR=$P(LN,TAG,2,999),LNTR=$TR(LNTR,$C(9,32)) ; Get rest of line, Remove spaces and tabs + . . . . I $E(LNTR)=";" QUIT ; Comment + . . . . S @GL@(RTN,TAG,0)=LN ; Otherwise, store for testing + . . . S I=0 ; Start offsets from zero (first one at the for will be 1) + . . I $C(32,9)[$E(LN) D QUIT ; Regular line + . . . N LNTR S LNTR=$TR(LN,$C(32,9)) ; Remove all spaces and tabs + . . . I $E(LNTR)=";" QUIT ; Comment line -- don't want. + . . . S @GL@(RTN,TAG,I)=LN ; Record line + QUIT + ; +ACTLINES(GL) ; [Private] $$ ; Count active lines + ; + N CNT S CNT=0 + N REF S REF=GL + N GLQL S GLQL=$QL(GL) + F S REF=$Q(@REF) Q:REF="" Q:(GL'=$NA(@REF,GLQL)) D + . N REFQL S REFQL=$QL(REF) + . N LASTSUB S LASTSUB=$QS(REF,REFQL) + . I LASTSUB?1.N S CNT=CNT+1 + QUIT CNT + ; +COVCOV(C,R) ; [Private] - Analyze coverage Cohort vs Result + N RTN S RTN="" + F S RTN=$O(@C@(RTN)) Q:RTN="" D ; For each routine in cohort set + . I '$D(@R@(RTN)) QUIT ; Not present in result set + . N TAG S TAG="" + . F S TAG=$O(@R@(RTN,TAG)) Q:TAG="" D ; For each tag in the routine in the result set + . . N LN S LN="" + . . F S LN=$O(@R@(RTN,TAG,LN)) Q:LN="" D ; for each line in the tag in the routine in the result set + . . . I $D(@C@(RTN,TAG,LN)) K ^(LN) ; if present in cohort, kill off + QUIT + ; +COVRPT(C,S,R,V) ; [Private] - Coverage Report + ; C = COHORT - Global name + ; S = SURVIVORS - Global name + ; R = RESULT - Global name + ; V = Verbosity - Scalar from -1 to 3 + N ORIGLINES S ORIGLINES=$$ACTLINES(C) + N LEFTLINES S LEFTLINES=$$ACTLINES(S) + W !! + W "ORIG: "_ORIGLINES,! + W "LEFT: "_LEFTLINES,! + W "COVERAGE PERCENTAGE: "_$S(ORIGLINES:$J(ORIGLINES-LEFTLINES/ORIGLINES*100,"",2),1:100.00),! + W !! + W "BY ROUTINE:",! + I V=0 QUIT ; No verbosity. Don't print routine detail + N RTN S RTN="" + F S RTN=$O(@C@(RTN)) Q:RTN="" D + . N O S O=$$ACTLINES($NA(@C@(RTN))) + . N L S L=$$ACTLINES($NA(@S@(RTN))) + . W ?3,RTN,?21,$S(O:$J(O-L/O*100,"",2),1:"100.00"),! + . I V=1 QUIT ; Just print the routine coverage for V=1 + . N TAG S TAG="" + . F S TAG=$O(@C@(RTN,TAG)) Q:TAG="" D + . . N O S O=$$ACTLINES($NA(@C@(RTN,TAG))) + . . N L S L=$$ACTLINES($NA(@S@(RTN,TAG))) + . . W ?5,TAG,?21,$S(O:$J(O-L/O*100,"",2),1:"100.00"),! + . . I V=2 QUIT ; Just print routine/tags coverage for V=2; V=3 print uncovered lines + . . N LN S LN="" + . . F S LN=$O(@S@(RTN,TAG,LN)) Q:LN="" W TAG_"+"_LN_": "_^(LN),! + QUIT + ; +COVRPTGL(C,S,R,OUT) ; [Private] - Coverage Global for silent invokers + ; C = COHORT - Global name + ; S = SURVIVORS - Global name + ; R = RESULT - Global name + ; OUT = OUTPUT - Global name + ; + N O S O=$$ACTLINES(C) + N L S L=$$ACTLINES(S) + S @OUT=(O-L)_"/"_O + N RTN,TAG,LN S (RTN,TAG,LN)="" + F S RTN=$O(@C@(RTN)) Q:RTN="" D + . N O S O=$$ACTLINES($NA(@C@(RTN))) + . N L S L=$$ACTLINES($NA(@S@(RTN))) + . S @OUT@(RTN)=(O-L)_"/"_O + . F S TAG=$O(@C@(RTN,TAG)) Q:TAG="" D + . . N O S O=$$ACTLINES($NA(@C@(RTN,TAG))) + . . N L S L=$$ACTLINES($NA(@S@(RTN,TAG))) + . . S @OUT@(RTN,TAG)=(O-L)_"/"_O + . . F S LN=$O(@S@(RTN,TAG,LN)) Q:LN="" S @OUT@(RTN,TAG,LN)=@S@(RTN,TAG,LN) + QUIT + ; +TESTCOVR ; entry under coverage analysis + D ENTRY^%uttcovr ; does analysis while running various unit tests + Q + ; diff --git a/Routines/%utt1.m b/Routines/%utt1.m new file mode 100644 index 0000000..faa5d59 --- /dev/null +++ b/Routines/%utt1.m @@ -0,0 +1,149 @@ +%utt1 ; VEN/SMH - Testing routines for M-Unit;08/28/14 11:42 + ;;0.1;MASH UTILITIES; +%utNITT ; VEN/SMH - Testing routines for M-Unit;2014-04-01 2:04 PM + ; + ; THIS ROUTINE IS THE UNIFIED UNIT TESTER FOR ALL OF M-UNIT. + ; + ; Dear Users, + ; + ; I know about about the irony of a test suite for the testing suite, + ; so stop snikering. Aside from that, it's actually going to be hard. + ; + ; Truly yours, + ; + ; Sam H + ; + D EN^%ut($T(+0),1) ; Run tests here, be verbose. + QUIT + ; +STARTUP ; M-Unit Start-Up - This runs before anything else. + S ^TMP($J,"%ut","STARTUP")="" + S KBANCOUNT=1 + QUIT + ; +SHUTDOWN ; M-Unit Shutdown - This runs after everything else is done. + K ^TMP($J,"%ut","STARTUP") + K KBANCOUNT + QUIT + ; + ; + ; +SETUP ; This runs before every test. + S KBANCOUNT=KBANCOUNT+1 + QUIT + ; +TEARDOWN ; This runs after every test + S KBANCOUNT=KBANCOUNT-1 + QUIT + ; + ; + ; +T1 ; @TEST - Make sure Start-up Ran + D CHKTF($D(^TMP($J,"%ut","STARTUP")),"Start-up node on ^TMP must exist") + QUIT + ; +T2 ; @TEST - Make sure Set-up runs + D CHKEQ(KBANCOUNT,2,"KBANCount not incremented properly at SETUP") + QUIT + ; +T3 ; @TEST - Make sure Teardown runs + D CHKEQ(KBANCOUNT,2,"KBANCount not decremented properly at TEARDOWN") + QUIT + ; +T4 ; Specified in XTMTAG + ; 140731 JLI - note that this will fail when run from the GUI runner, since it calls each tag separately + I $G(%utGUI) D CHKEQ(%utETRY,"T4","T4 should be the value for %utETRY in the GUI Runner") + I '$G(%utGUI) D CHKEQ(%utETRY(4),"T4","T4 should be the collected as the fourth entry in %utETRY") + QUIT + ; +T5 ; ditto + D CHKTF(0,"This is an intentional failure.") + D CHKEQ(%ut("FAIL"),1,"By this point, we should have failed one test") + D FAIL^%ut("Intentionally throwing a failure") + D CHKEQ(%ut("FAIL"),2,"By this point, we should have failed two tests") + ; S %ut("FAIL")=0 ; Okay... Boy's and Girls... as the developer I can do that. + QUIT + ; +T6 ; ditto + N TESTCOUNT S TESTCOUNT=%ut("CHK") + D SUCCEED^%ut + D SUCCEED^%ut + D CHKEQ(%ut("CHK"),TESTCOUNT+2,"Succeed should increment the number of tests") + QUIT + ; +T7 ; Make sure we write to principal even though we are on another device + ; This is a rather difficult test to carry out for GT.M and Cache... + N D + I +$SY=47 S D="/tmp/test.txt" ; All GT.M ; VMS not supported. + I +$SY=0 D ; All Cache + . I $ZVERSION(1)=2 S D=$SYSTEM.Util.GetEnviron("temp")_"\test.txt" I 1 ; Windows + . E S D="/tmp/test.txt" ; not windows; VMS not supported. + I +$SY=0 O D:"NWS" ; Cache new file + I +$SY=47 O D:(newversion) ; GT.M new file + U D + WRITE "HELLO",! + WRITE "HELLO",! + C D + ; + ; Now open back the file, and read the hello, but open in read only so + ; M-Unit will error out if it will write something out there. + ; + ; Per VISTA conventions, current IO device should be IO, old is IO(0). + ; + I +$SY=0 O D:"R" + I +$SY=47 O D:(readonly) + U D + N X READ X:1 + D CHKTF(X="HELLO") ; This should write to the screen the dot not to the file. + D CHKTF(($$LO($IO)=$$LO(D)),"IO device didn't get reset back") ; $$LO is b/c of a bug in Cache/Windows. $IO is not the same cas D. + I +$SY=0 C D:"D" + I +$SY=47 C D:(delete) + U $P + S IO=$IO + QUIT + ; + ; At the moment T8^%utt1 throws a fail, with no message + ; in the GUI runner. For some reason, both X and Y + ; variables are returned as null strings, while in the + ; command line runner, Y has a value containing the + ; word being sought + ; +T8 ; If IO starts with another device, write to that device as if it's the pricipal device + N D + I +$SY=47 S D="/tmp/test.txt" ; All GT.M ; VMS not supported. + I +$SY=0 D ; All Cache + . I $ZVERSION(1)=2 S D=$SYSTEM.Util.GetEnviron("temp")_"\test.txt" I 1 ; Windows + . E S D="/tmp/test.txt" ; not windows; VMS not supported. + I +$SY=0 O D:"NWS" ; Cache new file + I +$SY=47 O D:(newversion) ; GT.M new file + S IO=D + U D + D ^%utt4 ; Run some Unit Tests + C D + I +$SY=0 O D:"R" ; Cache read only + I +$SY=47 O D:(readonly) ; GT.M read only + U D + N X,Y R X:1,Y:1 + I +$SY=0 C D:"D" + I +$SY=47 C D:(delete) + D CHKTF(Y["MAIN") + S IO=$P + QUIT + ; +LO(X) Q $TR(X,"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz") + ; Shortcut methods for M-Unit +CHKTF(X,Y) D CHKTF^%ut(X,$G(Y)) QUIT +CHKEQ(A,B,M) D CHKEQ^%ut(A,B,$G(M)) QUIT + ; +XTENT ; Entry points + ;;T4;Entry point using XTMENT + ;;T5;Error count check + ;;T6;Succeed Entry Point + ;;T7;Make sure we write to principal even though we are on another device + ;;T8;If IO starts with another device, write to that device as if it's the pricipal device + ; +XTROU ; Routines containing additional tests + ;;%utt2; old %utNITU + ;;%utt4; old %utNITW + ;;%utt5; + ;;%utt6; diff --git a/Routines/%utt2.m b/Routines/%utt2.m new file mode 100644 index 0000000..4b42d24 --- /dev/null +++ b/Routines/%utt2.m @@ -0,0 +1,12 @@ +%utt2 ; VEN/SMH - Bad Ass Continuation of Unit Tests;08/04/14 09:12 + ;;0.1;MASH UTILITIES; +XTMUNITU ; VEN/SMH - Bad Ass Continuation of Unit Tests;2014-04-01 1:03 PM + ; +T11 ; @TEST An @TEST Entry point in Another Routine invoked through XTROU offsets + D CHKTF^%ut(1) + QUIT +T12 ; + D CHKTF^%ut(1) + QUIT +XTENT ; + ;;T12;An XTENT offset entry point in Another Routine invoked through XTROU offsets diff --git a/Routines/%utt3.m b/Routines/%utt3.m new file mode 100644 index 0000000..b55fec1 --- /dev/null +++ b/Routines/%utt3.m @@ -0,0 +1,43 @@ +%utt3 ; VEN/SMH - Unit Tests Coverage Tests;08/14/14 14:02 + ;;0.1;MASH UTILITIES; +XTMUNITV ; VEN/SMH - Unit Tests Coverage Tests;2014-04-16 7:14 PM + ; + ; *** BE VERY CAREFUL IN MODIFIYING THIS ROUTINE *** + ; *** THE UNIT TEST COUNTS ACTIVE AND INACTIVE LINES OF CODE *** + ; *** IF YOU MODIFY THIS, MODIFY XTMUNITW AS WELL *** + ; + ; Coverage tester in %utt4 + ; 20 Lines of code + ; 5 do not run as they are dead code + ; Expected Coverage: 15/20 = 75% + ; +STARTUP ; Doesn't count + N X ; Counts + S X=1 ; Counts + QUIT ; Counts + ; +SHUTDOWN K X,Y QUIT ; Counts; ZEXCEPT: X,Y + ; +SETUP S Y=$G(Y)+1 QUIT ; Counts + ; +TEARDOWN ; Doesn't count + S Y=Y-1 ; Counts + QUIT ; Counts + ; +T1 ; @TEST Test 1 + D CHKTF^%ut($D(Y)) ; Counts + QUIT ; Counts + ; +T2 ; @TEST Test 2 + D INTERNAL(1) ; Counts + D CHKTF^%ut(1) ; Counts + QUIT ; Counts + S X=1 ; Dead code + QUIT ; Dead code + ; +INTERNAL(A) ; Counts + S A=A+1 ; Counts + QUIT ; Counts + S A=2 ; Dead code + S Y=2 ; Dead code + QUIT ; Dead code diff --git a/Routines/%utt4.m b/Routines/%utt4.m new file mode 100644 index 0000000..5ee6712 --- /dev/null +++ b/Routines/%utt4.m @@ -0,0 +1,22 @@ +%utt4 ; VEN/SMH - Coverage Test Runner;2014-08-28 8:37 PM + ;;0.1;MASH UTILITIES; +XTMUNITW ; VEN/SMH - Coverage Test Runner;2014-04-17 3:30 PM + ;;7.3;KERNEL TOOLKIT;; + ; + ; This tests code in XTMUNITV for coverage + D EN^%ut($T(+0),1) QUIT + ; +MAIN ; @TEST - Test coverage calculations + Q:$D(^TMP("%uttcovr",$J)) ; already running coverage analysis from %uttcovr + Q:$$ISUTEST^%ut ; already running a unit test + Q:'(+$SY=47) ; GT.M ONLY + ;D COV^%ut1("XTMUNITV","D EN^%ut(""XTMUNITV"",1)",-1) ; Only produce output global. + D COV^%ut1("%utt3","D EN^%ut(""%utt3"",1)",-1) ; Only produce output global. + D CHKEQ^%ut(^TMP("%utCOVREPORT",$J),"15/20") + ;D CHKEQ^%ut(^TMP("XTMCOVREPORT",$J,"XTMUNITV","INTERNAL"),"3/6") + D CHKEQ^%ut(^TMP("%utCOVREPORT",$J,"%utt3","INTERNAL"),"3/6") + ;D CHKTF^%ut($D(^TMP("XTMCOVREPORT",$J,"XTMUNITV","T2",4))) + D CHKTF^%ut($D(^TMP("%utCOVREPORT",$J,"%utt3","T2",4))) + ;D CHKEQ^%ut(^TMP("XTMCOVREPORT",$J,"XTMUNITV","SETUP"),"1/1") + D CHKEQ^%ut(^TMP("%utCOVREPORT",$J,"%utt3","SETUP"),"1/1") + QUIT diff --git a/Routines/%utt5.m b/Routines/%utt5.m new file mode 100644 index 0000000..6978a06 --- /dev/null +++ b/Routines/%utt5.m @@ -0,0 +1,123 @@ +%utt5 ;JLI - test for aspects of MUnit functionality ;08/24/14 21:31 + ;;0.1;MASH UTILITIES; + Q + ; +OLDSTYLE ; + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %ut("ENT")="OLDSTYLE",%utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"OLDSTYLE")="" + D CHKEQ^%ut(5,5,"SET EQUAL ON PURPOSE - OLDSTYLE DONE") + D CHKTF^%ut(4=4,"MY EQUAL VALUE") + Q + ; +OLDSTYL1 ; + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %ut("ENT")="OLDSTYL1",%utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"OLDSTYL1")="" + D CHKEQ^%ut(4,4,"SET EQUAL ON PURPOSE - OLDSTYL1 DONE") + Q + ; +NEWSTYLE ; @TEST identify new style test indicator functionality + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %ut("ENT")="NEWSTYLE" S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"NEWSTYLE")="" + D CHKEQ^%ut(4,4,"SET EQUAL ON PURPOSE - NEWSTYLE DONE") + Q + ; +BADCHKEQ ; + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %ut("ENT")="BADCHKEQ" S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"BADCHKEQ")="" + D CHKEQ^%ut(4,3,"SET UNEQUAL ON PURPOSE - SHOULD FAIL") + Q + ; +BADCHKTF ; + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %ut("ENT")="BADCHKTF" S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"BADCHKTF")="" + D CHKTF^%ut(0,"SET FALSE (0) ON PURPOSE - SHOULD FAIL") + Q + ; +BADERROR ; + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + N X + I $D(%utt6var) S %ut("ENT")="BADERROR" S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"BADERROR")="" + ; following syntax error is on purpose to throw an error + S X= ; syntax error on purpose + Q + ; +CALLFAIL ; + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + N X + I $D(%utt6var) S %ut("ENT")="CALLFAIL" S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"CALLFAIL")="" + D FAIL^%ut("Called FAIL to test it") + Q + ; +LEAKSOK ; + N CODE,LOCATN,MYVALS,X + S CODE="S X=$$NOW^XLFDT()",LOCATN="LEAKSOK TEST",MYVALS("X")="" + D CHKLEAKS^%ut(CODE,LOCATN,.MYVALS) ; should find no leaks + Q + ; +LEAKSBAD ; + N CODE,LOCATN,MYVALS,X + S CODE="S X=$$NOW^XLFDT()",LOCATN="LEAKSBAD TEST - X NOT SPECIFIED" + D CHKLEAKS^%ut(CODE,LOCATN,.MYVALS) ; should find X since it isn't indicated + Q + ; +NVLDARG1 ; + D CHKEQ^%ut(1) + Q + ; +ISUTEST ; + D CHKTF^%ut($$ISUTEST^%ut,"ISUTEST returned FALSE!") + Q + ; +BADFORM1(X) ; @TEST should not be selected - arguments + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %ut("ENT")="NEWSTYLE" S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"BADFORM1")="" + D CHKEQ^%ut(4,3,"SHOULD NOT BE SELECTED - ARGUMENTS - BADFORM1") + Q + ; +BADFORM2 ; ABC @TEST should not be selected - @TEST NOT FIRST + ; ZEXCEPT: %ut - Newed in EN^%zu + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"BADFORM2")="" + D CHKEQ^%ut(4,3,"SHOULD NOT BE SELECTED - @TEST NOT FIRST - BADFORM2") + Q + ; +STARTUP ; + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var),$D(^TMP("%utt5",$J)) K ^TMP("%utt5",$J) + I $D(%utt6var) S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"STARTUP")="" + Q + ; +SHUTDOWN ; + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"SHUTDOWN")="" + Q + ; +SETUP ; + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"SETUP")="" + Q + ; +TEARDOWN ; + ; ZEXCEPT: %utt6cnt,%utt6var - if present, NEWED following top entry of routine %utt6 + I $D(%utt6var) S %utt6cnt=$G(%utt6cnt)+1,^TMP("%utt5",$J,%utt6cnt,"TEARDOWN")="" + Q + ; +XTENT ; + ;;OLDSTYLE; identify old style test indicator functionality + ;;OLDSTYL1; identify old style test indicator 2 + ;;BADCHKEQ; CHKEQ should fail on unequal value + ;;BADCHKTF; CHKTF should fail on false value + ;;BADERROR; throws an error on purpose + ;;CALLFAIL; called FAIL to test it + ;;LEAKSOK;check leaks should be ok + ;;LEAKSBAD;check leaks with leak + ;;NVLDARG1;check invalid arg in CHKEQ + ;;ISUTEST;check ISUTEST inside unit test diff --git a/Routines/%utt6.m b/Routines/%utt6.m new file mode 100644 index 0000000..a4aef02 --- /dev/null +++ b/Routines/%utt6.m @@ -0,0 +1,110 @@ +%utt6 ;JLI - Unit tests for MUnit functionality ;08/28/14 11:52 + ;;0.1;MASH UTILITIES; + ; + ; This routine uses ZZUTJLI2 as a test routine, it does not include the routine as an extension, + ; since it uses it for tests. + ; + ; ZZUTJLI2 currently contains 3 tests (2 old style, 1 new style), it also specifies STARTUP and + ; SHUTDOWN (should be 1 each) and SETUP and TEARDOWN (should be 3 each, 1 for each test) enteries, each of these + ; creates an entry under the ^TMP("ZZUTJLI2" global node, indicating function then continues the process. + ; Should be 2+3n entries (1+1 for STARTUP and SHUTDOWN, then 3 for each of the tests (SETUP, test, + ; and TEARDOWN). + ; + ; This first section is more of a functional test, since it checks the full unit test processing from both + ; a command line and a GUI call approach. Data for analysis is saved under ^TMP("ZZUTJLI2_C", for command + ; line and ^TMP("ZZUTJLI2_G", for gui processing. + ; + ; The counts for the command line processing are based on the number of unit test tags + ; determined for the GUI processing as well. The numbers are 2 (startup and shutdown) + ; + 3 x the number of tests present. + ; + ; run unit tests by command line + N VERBOSE + S VERBOSE=0 +VERBOSE ; + I '$D(VERBOSE) N VERBOSE S VERBOSE=1 + N ZZUTCNT,JLICNT,JLIEXPCT,JLII,JLIX,ZZUTRSLT,%utt5,%utt6,%utt6var + W !!,"RUNNING COMMAND LINE TESTS VIA DOSET^%ut",! + D DOSET^%ut(1,VERBOSE) ; run `1 in M-UNIT TEST GROUP file + ; + W !!!,"Running command line tests by RUNSET^%ut",! + D RUNSET^%ut("TESTS FOR UNIT TEST ROUTINES") + ; + ; Call GUISET to obtain list of tags via entry in M-UNIT TEST GROUP file + ; silent to the user + D GUISET^%ut(.%utt6,1) + K ^TMP("%utt6_GUISET",$J) M ^TMP("%utt6_GUISET",$J)=@%utt6 + ; + W !!!,"RUNNING COMMAND LINE UNIT TESTS FOR %utt5",! + N ZZUTCNT,JLICNT,JLIEXPCT,JLII,JLIX,ZZUTRSLT + S ZZUTCNT=0 + K ^TMP("%utt5",$J) ; kill any contents of data storage + D EN^%ut("%utt5",VERBOSE) ; should do STARTUP(1x), then SETUP, test, TEARDOWN (each together 3x) and SHUTDOWN (1x) + K ^TMP("%utt5_C",$J) M ^TMP("%utt5_C",$J)=^TMP("%utt5",$J) + ; + ; now run unit tests by GUI - first determines unit test tags + W !!!,"RUNNING UNIT TESTS FOR %utt5 VIA GUI CALLS - Silent",! + S ZZUTCNT=0 + K ^TMP("%utt5",$J),^TMP("%utt6",$J) + D GUILOAD^%ut(.%utt6,"%utt5") + M ^TMP("%utt6",$J)=@%utt6 + S %utt6=$NA(^TMP("%utt6",$J)) + ; then run each tag separately + ; JLICNT is count of unit test tags, which can be determined for GUI call for each unit test tag + S JLICNT=0 F JLII=1:1 S JLIX=$G(@%utt6@(JLII)) Q:JLIX="" I $P(JLIX,U,2)'="" S JLICNT=JLICNT+1 D GUINEXT^%ut(.ZZUTRSLT,$P(JLIX,U,2)_U_$P(JLIX,U)) + ; and close it with a null routine name + D GUINEXT^%ut(.ZZUTRSLT,"") + K ^TMP("%utt5_G",$J) M ^TMP("%utt5_G",$J)=^TMP("%utt5",$J) + S JLIEXPCT=2+(3*JLICNT) ; number of lines that should be in the global nodes for command line and GUI + ; + ; now run the unit tests in this routine + W !!,"NOW RUNNING UNIT TESTS FOR %utt6",!! + D EN^%ut("%utt6",VERBOSE) + K ^TMP("%utt5",$J),^TMP("%utt5_C",$J),^TMP("%utt5_G",$J),^TMP("%utt6",$J),^TMP("%utt6_GUISET",$J) + Q + ; + ; + ; WARNING -- WARNING -- WARNING + ; If the number of NEW STYLE tests in %utt5 is increased (it is currently 1), then the following + ; test will need to be updated to reflect the change(s) + ; END OF WARNING -- END OF WARNING -- END OF WARNING + ; +NEWSTYLE ; tests return of valid new style or @TEST indicators + N LIST + D NEWSTYLE^%ut1(.LIST,"%utt5") + D CHKEQ^%ut(LIST,1,"Returned an incorrect number ("_LIST_") of New Style indicators - should be one") + I LIST>0 D CHKEQ^%ut(LIST(1),"NEWSTYLE^identify new style test indicator functionality","Returned incorrect TAG^reason "_LIST(1)) + I LIST>0 D CHKEQ^%ut($G(LIST(2)),"","Returned a value for LIST(2) - should not have any value (i.e., null)") + Q + ; +CKGUISET ; + ; ZEXCEPT: %utt6var - if present, is NEWed and created in code following VERBOSE + I '$D(%utt6var) Q + N MAX + S MAX=$O(^TMP("%utt6_GUISET",$J,""),-1) + D CHKTF^%ut(^TMP("%utt6_GUISET",$J,MAX)["%utt6^NEWSTYLE","GUISET returned incorrect list") + Q + ; +CHKCMDLN ; check command line processing of %utt5 + ; ZEXCEPT: JLIEXPCT,%utt6var - if present NEWed and created in code following VERBOSE tag + I '$D(%utt6var) Q + D CHKTF^%ut($D(^TMP("%utt5_C",$J,JLIEXPCT))=10,"Not enough entries in %utt5 expected "_JLIEXPCT) + D CHKTF^%ut($D(^TMP("%utt5_C",$J,JLIEXPCT+1))=0,"Too many entries in %utt5 expected "_JLIEXPCT) + D CHKTF^%ut($O(^TMP("%utt5_C",$J,1,""))="STARTUP","Incorrect function for entry 1,'"_$O(^TMP("%utt5_C",$J,1,""))_"' should be 'STARTUP'") + D CHKTF^%ut($O(^TMP("%utt5_C",$J,JLIEXPCT,""))="SHUTDOWN","Incorrect function for entry "_JLIEXPCT_", '"_$O(^TMP("%utt5_C",$J,JLIEXPCT,""))_"' should be 'SHUTDOWN'") + Q + ; +CHKGUI ; check GUI processing of %utt5 + ; ZEXCEPT: JLIEXPCT,%utt6var - if present NEWed and created in code following VERBOSE tag + I '$D(%utt6var) Q + D CHKTF^%ut($D(^TMP("%utt5_G",$J,JLIEXPCT))=10,"Not enough entries in %utt5 expected "_JLIEXPCT) + D CHKTF^%ut($D(^TMP("%utt5_G",$J,JLIEXPCT+1))=0,"Too many entries in %utt5 expected "_JLIEXPCT) + D CHKTF^%ut($O(^TMP("%utt5_G",$J,1,""))="STARTUP","Incorrect function for entry 1,'"_$O(^TMP("%utt5Z_G",1,""))_"' should be 'STARTUP'") + D CHKTF^%ut($O(^TMP("%utt5_G",$J,JLIEXPCT,""))="SHUTDOWN","Incorrect function for entry "_JLIEXPCT_", '"_$O(^TMP("%utt5_G",$J,JLIEXPCT,""))_"' should be 'SHUTDOWN'") + Q + ; +XTENT ; + ;;CHKCMDLN;check command line processing of %utt5 + ;;CHKGUI;check GUI processing of %utt5 + ;;CKGUISET;check list of tests returned by GUISET + ;;NEWSTYLE;test return of valid new style or @TEST indicators diff --git a/Routines/%uttcovr.m b/Routines/%uttcovr.m new file mode 100644 index 0000000..72df422 --- /dev/null +++ b/Routines/%uttcovr.m @@ -0,0 +1,46 @@ +%uttcovr ;JLI/JIVEYSOFT - runs coverage tests on %ut and %ut1 routines via unit tests ;2014-09-10 5:19 PM + ;;0.1;MASH UTILITIES; + ; + I '(+$SY=47) W !,"This coverage analysis is currently only available in GT.M" Q ; GT.M only! + ; + ; if SHOWALL is true (1) all coverage globals data are listed + ; if SHOWALL is false (0), only the %utCOVREPORT global is listed + I '$D(SHOWALL) N SHOWALL S SHOWALL=0 + ; set global node so %utt4 doesn't run its own analysis + S ^TMP("%uttcovr",$J)=1 + ; start analysis of %ut - it calls entry below + D COV^%ut1("%ut","D TESTCOVR^%ut",3) + D LIST("%ut") ; output results of analysis + ; start analysis of %ut1 + D COV^%ut1("%ut1","D TESTCOVR^%ut1",3) + D LIST("%ut1") + K ^TMP("%uttcovr",$J) + Q + ; +SHOWALL ; Entry to get all coverage globals listed + N SHOWALL + S SHOWALL=1 + D ^%uttcovr + Q + ; +ENTRY ; + D ^%utt1 ; verbose + D EN^%ut("%utt1") ; non-verbose + ; run tests from top of %utt6, runs both command line and gui analyses + D ^%utt6 ; non-verbose + D VERBOSE^%utt6 ; verbose + Q + ; +LIST(ROU) ; + ; ZEXCEPT: SHOWALL - NEWed and set in SHOWALL or entering at %uttcovr + N JOB,NAME,BASE,GLOB + S JOB=$J + W !!!,ROU_" COVERAGE ANALYSIS" + F NAME="%utCOVREPORT","%utCOVRESULT","%utCOVCOHORT","%utCOVCOHORTSAV" D + . I 'SHOWALL,NAME'="%utCOVREPORT" Q + . W !!!,NAME," GLOBAL DATA",! + . S BASE="^TMP("""_NAME_""","_JOB,GLOB=BASE_")" + . I $D(GLOB)#2 W !,GLOB,"=",$G(@GLOB) + . F S GLOB=$Q(@GLOB) Q:GLOB'[BASE I $D(GLOB)#2 W !,GLOB,"=",@GLOB + . Q + Q