Macros for SAS Application Developers
https://github.com/sasjs/core
Loading...
Searching...
No Matches
mx_execute.test.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Testing mx_execute.sas macro
4
5 Be sure to run <code>%let mcTestAppLoc=/Public/temp/macrocore;</code> when
6 running in Studio
7
8 <h4> SAS Macros </h4>
9 @li mp_abort.sas
10 @li mp_assert.sas
11 @li mx_createwebservice.sas
12 @li mx_execute.sas
13
14 @sasjslint {"maxLineLength": 84, "noUnusedMacros": false}
15**/
16
17filename ft15f001 temp;
18parmcards4;
19 %put Initialising sendObj: ;
20 %put _all_;
21 %webout(FETCH)
22 %webout(OPEN)
23 %macro x();
24 %if %symexist(sasjs_tables) %then %do i=1 %to %sysfunc(countw(&sasjs_tables));
25 %let table=%scan(&sasjs_tables,&i);
26 %webout(OBJ,&table,missing=STRING)
27 %end;
28 %else %do i=1 %to &_webin_file_count;
29 %webout(OBJ,&&_webin_name&i,missing=STRING)
30 %end;
31 %mend x; %x()
32 %webout(CLOSE)
33;;;;
34%mx_createwebservice(path=&mcTestAppLoc/services,name=sendObj)
35
36%mp_assert(
37 iftrue=(&syscc=0),
38 desc=No errors after service creation,
39 outds=work.test_results
40)
41
42/**
43 * Test 1 - send a dataset
44 */
45data work.somedata1 work.somedata2;
46 x=1;
47 y=' t"w"o';
48 z=.z;
49 y2=' two';
50 label x='x factor';
51 output;
52run;
53
54%mx_execute(&mcTestAppLoc/services/sendObj,
55 inputdatasets=work.somedata1 work.somedata2,
56 mdebug=1,
57 outlib=testlib1,
58 outref=test1
59)
60%let test1=FAIL;
61data _null_;
62 set testlib1.somedata1;
63 if x=1 and y=' t"w"o' and z="Z" and y2=' two' then call symputx('test1','PASS');
64 putlog (_all_)(=);
65run;
66
67%let test2=FAIL;
68data _null_;
69 set testlib1.somedata2;
70 if x=1 and y=' t"w"o' and z="Z" and y2=' two' then call symputx('test2','PASS');
71 putlog (_all_)(=);
72run;
73
74
75%mp_assert(
76 iftrue=(&test1=PASS),
77 desc=somedata1 created correctly,
78 outds=work.test_results
79)
80%mp_assert(
81 iftrue=(&test2=PASS),
82 desc=somedata2 created correctly,
83 outds=work.test_results
84)
85
86/**
87 * Test 2 - the default call writes no log dataset
88 */
89proc datasets lib=work nolist nowarn;
90 delete childlog;
91quit;
92%mx_execute(&mcTestAppLoc/services/sendObj,
93 inputdatasets=work.somedata1,
94 outlib=testlib3,
95 outref=test3
96)
97
98%mp_assert(
99 iftrue=(%sysfunc(exist(work.childlog))=0),
100 desc=Test 2 - no log dataset is written unless outlogds is asked for,
101 outds=work.test_results
102)
103
104/**
105 * Test 3 - the child log is kept when outlogds is supplied
106 */
107%mx_execute(&mcTestAppLoc/services/sendObj,
108 inputdatasets=work.somedata1,
109 outlib=testlib4,
110 outref=test4,
111 outlogds=work.childlog
112)
113
114/* The log arrives as text after the separator. SAS 9 has no log to return, so
115 * the expectation is met there without one - expressed here rather than with a
116 * platform %if, so the test stays one program on every platform. */
117%let logcase=FAIL;
118%let logsize=FAIL;
119data _null_;
120 length line $32767;
121 retain found 0;
122 n=0;
123 if exist('work.childlog') then do;
124 /* count from the descriptor: a do-until loop runs once on an empty
125 * dataset, which would report the SAS 9 empty log as one line */
126 dsid=open('work.childlog');
127 n=attrn(dsid,'NOBS');
128 rc=close(dsid);
129 if n>0 then do until(eof);
130 set work.childlog(keep=line) end=eof;
131 /* the service's first statement is a %put - it must be in the log */
132 if index(line,'Initialising sendObj') then found=1;
133 end;
134 end;
135 call symputx('loglines',n);
136 if "&mcTestPlatform"="SASMETA" then do;
137 /* documented: SAS 9 returns no child log, so the dataset exists with no
138 * rows - anything else means something was captured from nowhere */
139 call symputx('logcase',ifc(n=0,'PASS','FAIL'));
140 call symputx('logsize','PASS');
141 end;
142 else do;
143 call symputx('logcase',ifc(found,'PASS','FAIL'));
144 /* a fragment that happens to contain the first line would still pass the
145 * marker test, so pin the volume too */
146 call symputx('logsize',ifc(n>50,'PASS','FAIL'));
147 end;
148run;
149
150%mp_assert(
151 iftrue=("&logcase"="PASS"),
152 desc=Test 3 - the child log is captured when outlogds is supplied,
153 outds=work.test_results
154)
155
156%mp_assert(
157 iftrue=("&logsize"="PASS"),
158 desc=Test 3 - the captured log is the whole log not a fragment (&loglines lines),
159 outds=work.test_results
160)
161
162/**
163 * Test 4 - the outcome of a clean run is reported, not left in WORK
164 */
165%mx_execute(&mcTestAppLoc/services/sendObj,
166 inputdatasets=work.somedata1,
167 outlib=testlib5,
168 outref=test5,
169 outstatus=work.status5
170)
171
172%let state5=NONE;
173data _null_;
174 if not exist('work.status5') then stop;
175 set work.status5;
176 call symputx('state5',state);
177run;
178
179%mp_assert(
180 iftrue=("&state5"="completed"),
181 desc=Test 4 - a clean run reports state=completed,
182 outds=work.test_results
183)
184
185%mp_assert(
186 iftrue=(%sysfunc(exist(work.results))=0),
187 desc=Test 4 - no fixed-name table is left in the caller WORK,
188 outds=work.test_results
189)
190
191/**
192 * Test 5 - an aborted child is reported as canceled, with its message
193 */
194filename ft15f002 temp;
195data _null_;
196 file ft15f002;
197 /* the abort comes first, as it does in a real service: mp_abort opens the
198 * response itself, so nothing needs to precede it */
199 put '%mp_abort(iftrue=(1=1),msg=Deliberate abort);';
200run;
201/* code= must be named: mx_createwebservice defaults to ft15f001, which still
202 * holds the sendObj source, so the service would silently be a copy of it */
203%mx_createwebservice(path=&mcTestAppLoc/services,name=abortObj,code=ft15f002)
204
205%mx_execute(&mcTestAppLoc/services/abortObj,
206 outref=test6,
207 outstatus=work.status6
208)
209
210/* SAS 9 reports unknown - proc stp returns no job status - so that is the
211 * expected value there, and there is no child message to look for. */
212%let state6=NONE;
213%let msg6=;
214data _null_;
215 length expect $20;
216 if "&mcTestPlatform"="SASMETA" then expect='unknown';
217 else expect='canceled';
218 call symputx('expect6',expect);
219 if exist('work.status6') then do;
220 set work.status6;
221 call symputx('state6',state);
222 call symputx('msg6',errmsg);
223 end;
224run;
225
226%mp_assert(
227 iftrue=("&state6"="&expect6"),
228 desc=Test 5 - an aborted child reports its outcome,
229 outds=work.test_results
230)
231
232%let msgcase=FAIL;
233data _null_;
234 if "&mcTestPlatform"="SASMETA" then call symputx('msgcase','PASS');
235 else if %index("&msg6","Deliberate abort")>0 then call symputx('msgcase','PASS');
236run;
237
238%mp_assert(
239 iftrue=("&msgcase"="PASS"),
240 desc=Test 5 - the abort message from the child is reported,
241 outds=work.test_results
242)
243
244/**
245 * Test 5b - the abort message is the whole message, not what fits on one line
246 *
247 * The capture that fills errmsg stops at an escaped quote, and the variable
248 * held 256 bytes, so a message carrying either arrived truncated. Both are
249 * reported in full now.
250 */
251filename ft15f003 temp;
252data _null_;
253 file ft15f003;
254 put '%mp_abort(iftrue=(1=1),msg=%nrstr(alpha "quoted" beta));';
255run;
256
257%mx_createwebservice(path=&mcTestAppLoc/services,name=abortQuote,code=ft15f003)
258
259%mx_execute(&mcTestAppLoc/services/abortQuote,
260 outref=testsq,
261 outstatus=work.statusq
262)
263
264filename ft15f004 temp;
265data _null_;
266 file ft15f004;
267 length big $400;
268 big=repeat('a message that runs on ',20);
269 put '%mp_abort(iftrue=(1=1),msg=' big +(-1) ');';
270run;
271
272%mx_createwebservice(path=&mcTestAppLoc/services,name=abortLong,code=ft15f004)
273
274%mx_execute(&mcTestAppLoc/services/abortLong,
275 outref=testlg,
276 outstatus=work.statuslg
277)
278
279%let quote6=NONE;
280%let long6=0;
281data _null_;
282 if exist('work.statusq') then do;
283 set work.statusq;
284 if index(errmsg,'quoted" beta')>0 then call symputx('quote6','PASS');
285 else call symputx('quote6','FAIL');
286 end;
287 if exist('work.statuslg') then do;
288 set work.statuslg;
289 call symputx('long6',length(errmsg));
290 end;
291run;
292
293%mp_assert(
294 iftrue=("&quote6"="PASS" or "&mcTestPlatform"="SASMETA"),
295 desc=Test 5b - a quote in the child message survives,
296 outds=work.test_results
297)
298
299%mp_assert(
300 iftrue=(&long6>256 or "&mcTestPlatform"="SASMETA"),
301 desc=Test 5b - a long child message is reported in full (&long6 bytes),
302 outds=work.test_results
303)
304
305/**
306 * Test 6 - the plain default call, with no outref, outlib or outstatus
307 */
308/* clear what Test 3 left, so the assertion below is about this call only */
309proc datasets lib=work nolist nowarn;
310 delete childlog;
311quit;
312%mx_execute(&mcTestAppLoc/services/sendObj,
313 inputdatasets=work.somedata1
314)
315
316%mp_assert(
317 iftrue=(&syscc=0),
318 desc=Test 6 - the default call runs without error,
319 outds=work.test_results
320)
321
322%mp_assert(
323 iftrue=(%sysfunc(exist(work.childlog))=0 and %sysfunc(exist(work.results))=0),
324 desc=Test 6 - the default call leaves no log or flow table behind,
325 outds=work.test_results
326)