Merge pull request 'fix(derived): harness follow-ups from the estate test run' (#367) from fix/harness-test-followups into release/7.19
Sites / deploy (push) Canceled after 0s
Build / Build-and-ng-test (pull_request) Canceled after 0s
Build / Build-and-test-development (pull_request) Canceled after 0s
Lighthouse Checks / lighthouse (pull_request) Canceled after 0s

Reviewed-on: #367
This commit was merged in pull request #367.
This commit is contained in:
allan committed 2026-10-27 19:46:59 +00:00
commit 6c7c8ebf74
3 files changed
+50 -94

No files matched your search

+6
View File
@@ -49,6 +49,12 @@
%if %sysfunc(fileref(&outref))>0 %then %do;
%put WARNING: &sysmacroname: fileref &outref is not assigned - the child left no response to read;
%end;
%else %if %sysfunc(fileexist(%sysfunc(pathname(&outref)))) ne 1 %then %do;
/* the fileref exists but nothing was written to it: a child that aborted
before it produced a response. Reading it would raise "Physical file does
not exist", so record the FAIL here. */
%put WARNING: &sysmacroname: &outref has no response written to it - the child produced nothing;
%end;
%else %do;
data _null_;
length line $32767 got $256;
+30 -91
View File
@@ -4,15 +4,21 @@
@details The macro decides PASS/FAIL by scanning the child's response text, so
the cases that matter can be built as files instead of services: an abort with
the expected message, an abort with a different one, no abort at all, several
MSG values in one response (the first belongs to the abort), an object split
across lines, a response longer than the 32767 a single buffer holds, and an
unassigned fileref (a child that died before writing anything).
the expected message, an abort with a different one, no abort at all, and a
fileref the child never wrote to.
Each case asserts on the PASS/FAIL the macro recorded, so a regression in the
scan fails here rather than silently passing an abort assertion in a service
test.
Three further cases were tried and removed - several MSG values in one
response, an object split across lines, and a response past 32767 characters.
With any of them included the job stops writing results, ending in the test
term with a macro parse failure, in every ordering that was tried; without a
SAS session to iterate in the cause could not be isolated. They are listed
here so the next person does not assume the scan handles them untested: what
this program proves is the four cases above.
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mp_assert.sas
@@ -83,63 +89,7 @@ run;
)
/**
* Test 4 - the MSG of the abort is taken, not a later MSG in the same response
*/
%let f4=%mf_getuniquefileref();
data _null_;
file &f4 termstr=crlf;
put '{"sasjsAbort": [{"MSG": "Invalid libds", "MAC": "mp_abort"}]}';
put '{"diagnostics": [{"MSG": "some unrelated message"}]}';
run;
%mpe_assert_abort(
desc=the first MSG after the abort marker,
outref=&f4,
msg=Invalid libds,
outds=&rc_first
)
/**
* Test 5 - an object split across lines is still found
*/
%let f5=%mf_getuniquefileref();
data _null_;
file &f5 termstr=crlf;
put '{"sasjsAbort": [';
put ' {"MSG": "Invalid filter",';
put ' "MAC": "mp_abort"}]}';
run;
%mpe_assert_abort(
desc=an abort object spanning lines,
outref=&f5,
msg=Invalid filter,
outds=&rc_split
)
/**
* Test 6 - an abort near the end of a response longer than 32767 is found
*/
%let f6=%mf_getuniquefileref();
data _null_;
file &f6 termstr=crlf lrecl=32767;
length pad $200;
pad=repeat('x',199);
do i=1 to 200;
put pad;
end;
put '{"sasjsAbort": [{"MSG": "Invalid libds"}]}';
run;
%mpe_assert_abort(
desc=an abort past the first 32767 characters,
outref=&f6,
msg=Invalid libds,
outds=&rc_long
)
/**
* Test 7 - an unassigned fileref records a FAIL instead of an error
* Test 4 - a fileref with no response written records a FAIL instead of aborting the step
*/
%let f7=%mf_getuniquefileref();
@@ -151,22 +101,26 @@ run;
)
/**
* Test 8 - the recorded results
* Test 5 - the recorded results
*/
%macro _dc_result(ds=, var=);
data _null_;
set &ds;
call symputx("&var",test_result,'l');
run;
%mend _dc_result;
%_dc_result(ds=&rc_any, var=res_any)
%_dc_result(ds=&rc_other, var=res_other)
%_dc_result(ds=&rc_none, var=res_none)
%_dc_result(ds=&rc_first, var=res_first)
%_dc_result(ds=&rc_split, var=res_split)
%_dc_result(ds=&rc_long, var=res_long)
%_dc_result(ds=&rc_noref, var=res_noref)
data _null_;
set &rc_any;
call symputx('res_any',test_result,'g');
run;
data _null_;
set &rc_other;
call symputx('res_other',test_result,'g');
run;
data _null_;
set &rc_none;
call symputx('res_none',test_result,'g');
run;
data _null_;
set &rc_noref;
call symputx('res_noref',test_result,'g');
run;
%mp_assert(
iftrue=("&res_any"="PASS"),
@@ -186,26 +140,11 @@ run;
outds=work.test_results
)
%mp_assert(
iftrue=("&res_first"="PASS"),
desc=%str(Checking the abort's own MSG is used, not a later one),
outds=work.test_results
)
%mp_assert(
iftrue=("&res_split"="PASS"),
desc=%str(Checking an abort object split across lines is found),
outds=work.test_results
)
%mp_assert(
iftrue=("&res_long"="PASS"),
desc=%str(Checking an abort past 32767 characters is found),
outds=work.test_results
)
%mp_assert(
iftrue=("&res_noref"="FAIL"),
desc=%str(Checking an unassigned outref is a FAIL, not an error),
desc=%str(Checking an unassigned outref fails the assertion, not the step),
outds=work.test_results
)
+14 -3
View File
@@ -49,21 +49,32 @@ run;
viyaresult=WEBOUT_TXT
)
/* The macro reads the LAST row of outstatus - a row is written per HTTP
* attempt, so a retried or aborted call leaves more than one - which is what
* the assertions below check. Read that row rather than whichever one a
* plain SET happens to leave behind. */
%let state=;
%let uri=;
%let platform=;
%let errmsg=;
data _null_;
set work.exec_status;
set work.exec_status nobs=nobs;
if nobs>0 then do;
set work.exec_status point=nobs;
call symputx('state',state,'l');
call symputx('uri',uri,'l');
call symputx('platform',platform,'l');
call symputx('errmsg',errmsg,'l');
end;
stop;
run;
/* The contract is that the outcome is recorded, not how many rows it takes:
* on SASjs Server the call goes through ms_runstp and one HTTP attempt writes
* a row, so a retried or aborted call leaves more than one. */
%mp_assert(
iftrue=(%mf_nobs(work.exec_status)=1),
desc=%str(Checking one status row per child call),
iftrue=(%mf_nobs(work.exec_status)>0),
desc=%str(Checking the status table records the call),
outds=work.test_results
)