diff --git a/all.sas b/all.sas index 8ea36cd..7205750 100644 --- a/all.sas +++ b/all.sas @@ -3032,8 +3032,15 @@ run; makes it easy to detect whether any macro variables were modified or changed. - If you would like this feature, feel free to contribute / raise an issue / - engage the SASjs team directly. + The following variables are NOT tested (as they are known, global variables + used in SASjs): + + @li &sasjs_prefix._FUNCTIONS + + Global variables are initialised in mp_init.sas - which will also trigger + "strict mode" in your SAS session. Whilst this is a default in SASjs + produced apps, if you prefer not to use this mode, simply instantiate the + following variable to prevent the macro from running: `SASJS_PREFIX` Example usage: @@ -3054,6 +3061,8 @@ run; @param [in] scope= (GLOBAL) The scope of the variables to be checked. This corresponds to the values in the SCOPE column in `sashelp.vmacro`. @param [in] desc= (Testing scope leakage) The user provided test description + @param [in] ignorelist= Provide a list of macro variable names to ignore from + the comparison @param [in,out] scopeds= (work.mp_assertscope) The dataset to contain the scope snapshot @param [out] outds= (work.test_results) The output dataset to contain the @@ -3062,6 +3071,10 @@ run; |---|---|---| |User Provided description|PASS|No out of scope variables created or modified| +

SAS Macros

+ @li mf_getquotedstr.sas + @li mp_init.sas +

Related Macros

@li mp_assert.sas @li mp_assertcols.sas @@ -3078,9 +3091,18 @@ run; desc=Testing Scope Leakage, scope=GLOBAL, scopeds=work.mp_assertscope, + ignorelist=, outds=work.test_results )/*/STORE SOURCE*/; -%local ds test_result test_comments del add mod; +%local ds test_result test_comments del add mod ilist; +%let ilist=%upcase(&sasjs_prefix._FUNCTIONS &ignorelist); + +/** + * this sets up the global vars, it will also enter STRICT mode. If this + * behaviour is not desired, simply initiate the following global macro + * variable to prevent the macro from running: SASJS_PREFIX + */ +%mp_init() /* get current variables */ %if &action=SNAPSHOT %then %do; @@ -3088,7 +3110,7 @@ run; create table &scopeds as select name,offset,value from dictionary.macros - where scope="&scope" + where scope="&scope" and name not in (%mf_getquotedstr(&ilist)) order by name,offset; %end; %else %if &action=COMPARE %then %do; @@ -3097,7 +3119,7 @@ run; create table _data_ as select name,offset,value from dictionary.macros - where scope="&scope" + where scope="&scope" and name not in (%mf_getquotedstr(&ilist)) order by name,offset; %let ds=&syslast; @@ -10129,7 +10151,7 @@ create table &delrec as from &outdel a left join &base b on &keyjoin - where a.%scan(&key,1) is null + where b.%scan(&key,1) is null order by &commakey; data &delerr; @@ -10237,7 +10259,7 @@ select distinct tgtvar_nm into: missvars separated by ' ' from &outmod a left join &base b on &keyjoin - where a.%scan(&key,1) is null + where b.%scan(&key,1) is null order by &commakey; data &moderr; if 0 then set &errds; diff --git a/base/mp_assertscope.sas b/base/mp_assertscope.sas index 7910d10..e1dd54c 100644 --- a/base/mp_assertscope.sas +++ b/base/mp_assertscope.sas @@ -11,8 +11,15 @@ makes it easy to detect whether any macro variables were modified or changed. - If you would like this feature, feel free to contribute / raise an issue / - engage the SASjs team directly. + The following variables are NOT tested (as they are known, global variables + used in SASjs): + + @li &sasjs_prefix._FUNCTIONS + + Global variables are initialised in mp_init.sas - which will also trigger + "strict mode" in your SAS session. Whilst this is a default in SASjs + produced apps, if you prefer not to use this mode, simply instantiate the + following variable to prevent the macro from running: `SASJS_PREFIX` Example usage: @@ -33,6 +40,8 @@ @param [in] scope= (GLOBAL) The scope of the variables to be checked. This corresponds to the values in the SCOPE column in `sashelp.vmacro`. @param [in] desc= (Testing scope leakage) The user provided test description + @param [in] ignorelist= Provide a list of macro variable names to ignore from + the comparison @param [in,out] scopeds= (work.mp_assertscope) The dataset to contain the scope snapshot @param [out] outds= (work.test_results) The output dataset to contain the @@ -41,6 +50,10 @@ |---|---|---| |User Provided description|PASS|No out of scope variables created or modified| +

SAS Macros

+ @li mf_getquotedstr.sas + @li mp_init.sas +

Related Macros

@li mp_assert.sas @li mp_assertcols.sas @@ -57,9 +70,18 @@ desc=Testing Scope Leakage, scope=GLOBAL, scopeds=work.mp_assertscope, + ignorelist=, outds=work.test_results )/*/STORE SOURCE*/; -%local ds test_result test_comments del add mod; +%local ds test_result test_comments del add mod ilist; +%let ilist=%upcase(&sasjs_prefix._FUNCTIONS &ignorelist); + +/** + * this sets up the global vars, it will also enter STRICT mode. If this + * behaviour is not desired, simply initiate the following global macro + * variable to prevent the macro from running: SASJS_PREFIX + */ +%mp_init() /* get current variables */ %if &action=SNAPSHOT %then %do; @@ -67,7 +89,7 @@ create table &scopeds as select name,offset,value from dictionary.macros - where scope="&scope" + where scope="&scope" and name not in (%mf_getquotedstr(&ilist)) order by name,offset; %end; %else %if &action=COMPARE %then %do; @@ -76,7 +98,7 @@ create table _data_ as select name,offset,value from dictionary.macros - where scope="&scope" + where scope="&scope" and name not in (%mf_getquotedstr(&ilist)) order by name,offset; %let ds=&syslast; diff --git a/base/mp_stackdiffs.sas b/base/mp_stackdiffs.sas index 292a19b..e7fbe56 100644 --- a/base/mp_stackdiffs.sas +++ b/base/mp_stackdiffs.sas @@ -418,7 +418,7 @@ create table &delrec as from &outdel a left join &base b on &keyjoin - where a.%scan(&key,1) is null + where b.%scan(&key,1) is null order by &commakey; data &delerr; @@ -526,7 +526,7 @@ select distinct tgtvar_nm into: missvars separated by ' ' from &outmod a left join &base b on &keyjoin - where a.%scan(&key,1) is null + where b.%scan(&key,1) is null order by &commakey; data &moderr; if 0 then set &errds; diff --git a/tests/crossplatform/mp_stackdiffs.test.sas b/tests/crossplatform/mp_stackdiffs.test.sas index 83f02da..0fccf8d 100644 --- a/tests/crossplatform/mp_stackdiffs.test.sas +++ b/tests/crossplatform/mp_stackdiffs.test.sas @@ -45,13 +45,17 @@ run; %mp_assertscope(SNAPSHOT) /** - * Deletions test - where record does not exist + * Deletions test - where record does exist */ +data work.orig1; + set sashelp.electric; + if _n_ le 10; +run; data work.final1; set work.final; where move_type='D'; run; -%mp_stackdiffs(work.orig +%mp_stackdiffs(work.orig1 ,work.final1 ,CUSTOMER YEAR ,mdebug=1 @@ -69,11 +73,11 @@ run; test=EQUALS 10 ) /** - * Deletions test - where record DOES exist + * Deletions test - where record does NOT exist */ data work.orig2; - set sashelp.electric; - if _n_ le 10; + set work.orig; + stop; /* empty table */ run; data work.final2; set work.final; @@ -89,11 +93,11 @@ run; ,outdel=work.del2 ) %mp_assertdsobs(work.errds2, - desc=Delete1 - has errs, + desc=Delete2 - has errs, test=EQUALS 10 ) %mp_assertdsobs(work.del1, - desc=Delete1 - records not populated, + desc=Delete2 - records not populated, test=EQUALS 0 ) @@ -130,7 +134,9 @@ run; * Additions test - where record does exist */ data work.orig4; - set work.orig; + set sashelp.electric; + if _n_ ge 30; + year=_n_; if _n_>35 then stop; run; data work.final4; @@ -251,7 +257,7 @@ run; * And a test if the actual values were applied */ data work.orig8; - set work.orig; + set sashelp.electric; if _n_ le 16; run; %mp_stackdiffs(work.orig8 @@ -292,4 +298,4 @@ run; ) -%mp_assertscope(COMPARE,Desc=MacVar Scope Check) \ No newline at end of file +%mp_assertscope(COMPARE,ignorelist=SASJS_FUNCTIONS) \ No newline at end of file