1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Konrad Marek Zapalowicz
5 : * Contact e-mail: DG.MIN-Support@nokia.com
6 : *
7 : * This program is free software: you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the Free
9 : * Software Foundation, version 2 of the License.
10 : *
11 : * This program is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : * more details. You should have received a copy of the GNU General Public
15 : * License along with this program. If not, see
16 : * <http://www.gnu.org/licenses/>.
17 : */
18 :
19 :
20 : /**
21 : * @file min_scripter_if.c
22 : * @version 0.1
23 : * @brief This file contains implementation of MIN Scripter interface.
24 : */
25 :
26 : /* ------------------------------------------------------------------------- */
27 : /* INCLUDE FILES */
28 : #include <sched.h>
29 : #include <ctype.h>
30 :
31 : #include <dllist.h>
32 : #include <min_lego_interface.h>
33 : #include <min_scripter_if.h>
34 : #include <scripter_plugin.h>
35 : #include <scripter_common.h>
36 : #include <test_module_api.h>
37 : #include <min_test_interference.h>
38 : /* ------------------------------------------------------------------------- */
39 : /* EXTERNAL DATA STRUCTURES */
40 : /* None */
41 :
42 : /* ------------------------------------------------------------------------- */
43 : /* EXTERNAL GLOBAL VARIABLES */
44 :
45 : /* ------------------------------------------------------------------------- */
46 : /* EXTERNAL FUNCTION PROTOTYPES */
47 : /* ------------------------------------------------------------------------- */
48 : extern int scripter_init (minScripterIf * scripter_if);
49 : /* ------------------------------------------------------------------------- */
50 : /* GLOBAL VARIABLES */
51 : /* ------------------------------------------------------------------------- */
52 : TSBool stprun = ESFalse; /**< exit flag for scripted test process */
53 : TSBool ctprun = ESFalse; /**< exit flag for combined test process */
54 : struct scripter_mod_ scripter_mod;
55 : DLList *tp_handlers = INITPTR; /**< handles to tmapi fctions from TC*/
56 : DLList *allowedresults = INITPTR; /**< Allowed result codes. */
57 : DLList *allowederrors = INITPTR; /**< Allowed error codes. */
58 : DLList *defines = INITPTR; /**< Contains defintions */
59 : DLList *variables = INITPTR;/**< Contains scripter variables */
60 : DLList *interference_handles = INITPTR;/**<test interference "instances"*/
61 : /* ------------------------------------------------------------------------- */
62 : /* CONSTANTS */
63 : /* None */
64 :
65 : /* ------------------------------------------------------------------------- */
66 : /* MACROS */
67 : /** Reports scripter run time error with one argumen
68 : * @param __errstr__ the error string
69 : * @param __errarg__ error argument string
70 : */
71 : #define SCRIPTER_RTERR_ARG(__errstr__,__errarg__) \
72 : do { \
73 : MIN_ERROR (__errstr__,__errarg__); \
74 : snprintf (scripter_mod.script_tcr.desc_, MaxTestResultDescription, \
75 : "%s:%s:%d - %s [%s]", __FILE__,__FUNCTION__, __LINE__, \
76 : __errstr__, __errarg__); \
77 : scripter_mod.error_occured = ESTrue; \
78 : scripter_mod.script_tcr.result_ = TP_CRASHED; \
79 : } while (0)
80 :
81 : /** Reports scripter run time error
82 : * @param __errstr__ the error string
83 : */
84 : #define SCRIPTER_RTERR(__errstr__) \
85 : do { \
86 : MIN_ERROR (__errstr__); \
87 : snprintf (scripter_mod.script_tcr.desc_, MaxTestResultDescription, \
88 : "%s:%s:%d - %s",__FILE__, __FUNCTION__, __LINE__, \
89 : __errstr__); \
90 : scripter_mod.error_occured = ESTrue; \
91 : scripter_mod.script_tcr.result_ = TP_CRASHED; \
92 : } while (0)
93 :
94 : /* ------------------------------------------------------------------------- */
95 : /* LOCAL GLOBAL VARIABLES */
96 : /* None */
97 :
98 : /* ------------------------------------------------------------------------- */
99 : /* LOCAL CONSTANTS AND MACROS */
100 : /* None */
101 :
102 : /* ------------------------------------------------------------------------- */
103 : /* MODULE DATA STRUCTURES */
104 : /* ------------------------------------------------------------------------- */
105 : struct scripter_mod_ {
106 : minScripterIf min_scripter_if;/**< Interface to parser plugin */
107 : DLList *req_events; /**< Local requested events. */
108 : DLList *tp_details; /**< Global list of loaded modules. */
109 : int mqid; /**< Message Queue Id */
110 : TSBool script_finished; /**< Set when script end noticed */
111 : TSBool tclass_exec; /**< Set while class func running */
112 : TSBool paused; /**< Set when paused from the cui */
113 : TSBool extif_pending; /**< Waiting resp to ext cont. msg */
114 : TSBool event_pending; /**< Waiting for event ind */
115 : TSBool error_occured; /**< Run time error flag */
116 : unsigned int extif_remote; /**< number of remote test cases */
117 : char *testcomplete; /**< Complete test flag */
118 : TSBool canceliferror; /**< Cancels script if error in test*/
119 : unsigned long sleep; /**< Sleep enabled flag if this > 0 */
120 : struct timeval time; /**< Used for sleep realization */
121 : TestCaseResult script_tcr; /**< Scripted test case result */
122 : char *expected_var; /**< Variable we are expecting */
123 : int shm_id; /**< Shared segment ID */
124 : };
125 :
126 : typedef struct {
127 : char *name_;
128 : TSBool initialized_;
129 : char *value_;
130 : } ScriptVar;
131 :
132 : typedef struct {
133 : char name_[32];
134 : testInterference *instance_;
135 : } InterfHandle;
136 :
137 : /* ------------------------------------------------------------------------- */
138 : /* LOCAL FUNCTION PROTOTYPES */
139 : /* ------------------------------------------------------------------------- */
140 : /** Used for finding class name on list. */
141 : LOCAL int _findclass (const void *a, const void *b);
142 : /* ------------------------------------------------------------------------- */
143 : /** Used for finding test process of specified pid. */
144 : LOCAL int _findpid (const void *a, const void *b);
145 : /* ------------------------------------------------------------------------- */
146 : /** Used for finding test process of specified status. */
147 : LOCAL int _findstatus (const void *a, const void *b);
148 : /* ------------------------------------------------------------------------- */
149 : /** Used for finding test process of specified testid. */
150 : LOCAL int _findid (const void *a, const void *b);
151 : /* ------------------------------------------------------------------------- */
152 : /** Used for finding specified allowed result and also allowed error code */
153 : LOCAL int _findallowedresult (const void *a, const void *b);
154 : /* ------------------------------------------------------------------------- */
155 : /** Fetches pointer to run_method from library and stores it in safe place.
156 : * @param dllname [in] name of the library from which pointer is fetched.
157 : * @param classname [in] mnemonic for that library.
158 : */
159 : LOCAL void fetch_ptr2run (const char *dllname, const char *classname);
160 : /* ------------------------------------------------------------------------- */
161 : /** Reads possible optional parameter for the RUN keyword.
162 : * @param mip [in] line with possible parameters.
163 : * @param ep [out] structure that contains extra parameters */
164 : LOCAL void read_optional_run_params (MinItemParser * mip,
165 : ExtraParams * ep);
166 : /* ------------------------------------------------------------------------- */
167 : /** Message handling function. Calls appropiate message handler.
168 : * @param mqid [in] message queue id.
169 : * @param msg [in] buffer that contains message to be handled.
170 : */
171 : LOCAL void uengine_handle_message (int mqid, const MsgBuffer * msg);
172 : /* ------------------------------------------------------------------------- */
173 : /** Handles MSG_RET
174 : * @param mqid [in] message queue id.
175 : * @param param [in] test result code.
176 : * @param message [in] description of the test result.
177 : */
178 : LOCAL void uengine_handle_ret (int mqid, int param, const char *message,
179 : long sender);
180 : /* ------------------------------------------------------------------------- */
181 : /** Handles indication event.
182 : * @param mqid [in] message queue id.
183 : * @param msg [in] buffer that contains message to be handled.
184 : */
185 : LOCAL void uengine_handle_event_ind (int mqid, const MsgBuffer * msg);
186 : /* ------------------------------------------------------------------------- */
187 : /** Handles MSG_SNDRCV
188 : * @param mqid [in] message queue id.
189 : * @param msg [in] buffer that contains message to be handled.
190 : */
191 : LOCAL void uengine_handle_sndrcv (int mqid, const MsgBuffer * msg);
192 : /* ------------------------------------------------------------------------- */
193 : /** Handles MSG_END message.
194 : * @param mqid [in] message queue id.
195 : * @param msg [in] buffer that contains message to be handled.
196 : */
197 : LOCAL void uengine_handle_end (int mqid, const MsgBuffer * msg);
198 : /* ------------------------------------------------------------------------- */
199 : /** Handles MSG_PAUSE message.
200 : * @param mqid [in] message queue id.
201 : * @param msg [in] buffer that contains message to be handled.
202 : */
203 : LOCAL void uengine_handle_pause (int mqid, const MsgBuffer * msg);
204 : /* ------------------------------------------------------------------------- */
205 : /** Handles MSG_RESUME message.
206 : * @param mqid [in] message queue id.
207 : * @param msg [in] buffer that contains message to be handled.
208 : */
209 : LOCAL void uengine_handle_resume (int mqid, const MsgBuffer * msg);
210 : /* ------------------------------------------------------------------------- */
211 : /** Handles abort message.
212 : * @param mqid [in] message queue id.
213 : * @param msg [in] buffer that contains message to be handled.
214 : */
215 : LOCAL void uengine_handle_stop (int mqid, const MsgBuffer * msg);
216 : /* ------------------------------------------------------------------------- */
217 : /** Handles external controller message.
218 : * @param mqid [in] message queue id.
219 : * @param msg [in] buffer that contains message to be handled.
220 : */
221 : LOCAL void uengine_handle_extif (int mqid, const MsgBuffer * msg);
222 : /* ------------------------------------------------------------------------- */
223 : /** handles external controller message type EResponseSlave
224 : * @param result [in] the result of the operation: 1 = Ok, 0 = Error
225 : * @param caseid [in] the test case id, if caseid > 0
226 : */
227 : LOCAL void uengine_handle_extif_response (int result, int caseid);
228 : /* ------------------------------------------------------------------------- */
229 : /** handles external controller message type ERemoteSlaveResponse
230 : * @param testresult [in] test case result.
231 : * @param caseid [in] the test case id, if caseid > 0
232 : */
233 : LOCAL void uengine_handle_extif_remote_response (int testresult,
234 : int caseid);
235 : /* ------------------------------------------------------------------------- */
236 : /** Handler for SIGCHLD
237 : * @param sig signal numnber
238 : */
239 : /*LOCAL void scripter_sigchld_handler( int sig );*/
240 : /* ------------------------------------------------------------------------- */
241 : /** Handler for SIGALRM
242 : * @param sig signal numnber
243 : */
244 : LOCAL void scripter_sigalrm_handler (int sig);
245 : /* ------------------------------------------------------------------------- */
246 : /** Checks a few global flags to see if next line in script should be executed
247 : */
248 : LOCAL TSBool _execute_script (void);
249 : /* ------------------------------------------------------------------------- */
250 : /** Checks if there are test cases running
251 : */
252 : LOCAL TSBool _pending_tests (void);
253 : /* ------------------------------------------------------------------------- */
254 : /** List find compare function
255 : * @param a comparison lvalue
256 : * @param b comparison rvalue
257 : */
258 : LOCAL int _look4event (const void *a, const void *b);
259 : /* ------------------------------------------------------------------------- */
260 : /** Searches for event registration from a local list
261 : * @param eventname name of the envent
262 : */
263 : LOCAL minEventIf *find_event_reqistration (char *eventname);
264 : /* ------------------------------------------------------------------------- */
265 : /** Translates literal category to the enum representation.
266 : * @param str [in] literal category to be translated
267 : * @return enumerator value that correstonds to str @see TTestCategory
268 : */
269 : LOCAL TTestCategory get_result_category (const char *str);
270 : /* ------------------------------------------------------------------------- */
271 : /** Assigns a value to script variable
272 : * @param varname [in] variable name
273 : * @param varval [in] variable value
274 : */
275 : LOCAL void var_assign (const char *varname, const char *varval);
276 : /* ------------------------------------------------------------------------- */
277 : /** Updates the scriter internal variables
278 : * @param res [in] Test Process result
279 : */
280 : LOCAL void update_variables (TPResult res);
281 : /* ------------------------------------------------------------------------- */
282 : /** Used for declaring scripter interal variables
283 : * @param varname [in] variable name
284 : */
285 : LOCAL int declare_internal_var (const char *varname);
286 : /* ------------------------------------------------------------------------- */
287 : /** Interpretes the variable value as integer and increments by one
288 : * @param varname [in] variable name
289 : */
290 : LOCAL void var_increment (const char *varname);
291 : /* ------------------------------------------------------------------------- */
292 : /** Sends scripter variables to test class
293 : */
294 : LOCAL void send_variables ();
295 : /* ------------------------------------------------------------------------- */
296 : /** Receives scripter variables from test class
297 : */
298 : LOCAL void receive_variables ();
299 : /* ------------------------------------------------------------------------- */
300 : /** Inspects all the results of the method, combiner calls made from the script
301 : * and decides if the scripted test case is PASSED or FAILED
302 : * @param tp_details [in] list of method / combiner calls
303 : * @param tcr [in/out] the final result
304 : */
305 : LOCAL void scripter_final_verdict (DLList * tp_details,
306 : TestCaseResult * tcr);
307 :
308 : /* FORWARD DECLARATIONS */
309 : /* None */
310 :
311 : /* ------------------------------------------------------------------------- */
312 : /* ==================== LOCAL FUNCTIONS ==================================== */
313 : /* ------------------------------------------------------------------------- */
314 : /* ------------------------------------------------------------------------- */
315 : LOCAL int _findclass (const void *a, const void *b)
316 39 : {
317 39 : ScriptedTestProcessDetails *stpd = (ScriptedTestProcessDetails *) a;
318 39 : return strcmp (stpd->testclass_, (char *)b);
319 : }
320 :
321 : /* ------------------------------------------------------------------------- */
322 : LOCAL int _findpid (const void *a, const void *b)
323 37 : {
324 37 : ScriptedTestProcessDetails *stpd = (ScriptedTestProcessDetails *) a;
325 37 : if (stpd->pid_ == *(long *)b)
326 33 : return 0;
327 : else
328 4 : return 1;
329 : }
330 :
331 : /* ------------------------------------------------------------------------- */
332 : LOCAL int _findstatus (const void *a, const void *b)
333 46 : {
334 46 : ScriptedTestProcessDetails *stpd = (ScriptedTestProcessDetails *) a;
335 46 : if (stpd->status_ == *(int *)b)
336 12 : return 0;
337 : else
338 34 : return 1;
339 : }
340 :
341 : /* ------------------------------------------------------------------------- */
342 : LOCAL int _findid (const void *a, const void *b)
343 6 : {
344 6 : ScriptedTestProcessDetails *stpd = (ScriptedTestProcessDetails *) a;
345 6 : return strcmp (stpd->options_.testid_, (char *)b);
346 : }
347 :
348 : /* ------------------------------------------------------------------------- */
349 : LOCAL int _findallowedresult (const void *a, const void *b)
350 27 : {
351 27 : if (*(int *)a == *(int *)b)
352 27 : return 0;
353 : else
354 0 : return 1;
355 : }
356 :
357 : /* ------------------------------------------------------------------------- */
358 : LOCAL TSBool _pending_tests ()
359 36 : {
360 36 : DLListIterator it = DLListNULLIterator;
361 36 : int desiredstatus = TP_RUNNING;
362 :
363 36 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
364 : , dl_list_tail (scripter_mod.tp_details)
365 : , _findstatus, &desiredstatus);
366 :
367 36 : if (it != DLListNULLIterator)
368 10 : return ESTrue;
369 :
370 26 : desiredstatus = TP_PAUSED;
371 26 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
372 : , dl_list_tail (scripter_mod.tp_details)
373 : , _findstatus, &desiredstatus);
374 :
375 26 : if (it != DLListNULLIterator)
376 2 : return ESTrue;
377 :
378 24 : if (scripter_mod.tclass_exec)
379 0 : return ESTrue;
380 :
381 24 : if (scripter_mod.extif_remote > 0)
382 0 : return ESTrue;
383 :
384 24 : return ESFalse;
385 : }
386 :
387 : /* ------------------------------------------------------------------------- */
388 : LOCAL TSBool _execute_script ()
389 2760 : {
390 : struct timeval res;
391 : struct timeval now;
392 2760 : unsigned long elapsed = 0; /* in [ms] */
393 :
394 : /* If an error has occured do not investigate further,
395 : * otherwise we might get stuck (e.g. remote run + event)
396 : */
397 2760 : if (scripter_mod.error_occured)
398 0 : return ESTrue;
399 :
400 : /* Execute script only if its not finished */
401 2760 : if (scripter_mod.script_finished)
402 12 : return ESFalse;
403 :
404 : /* ...and if a blocking method is not running */
405 2748 : if (scripter_mod.tclass_exec)
406 33 : return ESFalse;
407 :
408 : /* ...and if we are not paused from the cui */
409 2715 : if (scripter_mod.paused)
410 0 : return ESFalse;
411 :
412 : /* ...and if we are not waiting for the
413 : * a response to external controller message */
414 2715 : if (scripter_mod.extif_pending)
415 1039 : return ESFalse;
416 :
417 : /* ...and if we are not waiting for the test to be completed */
418 1676 : if (scripter_mod.testcomplete != INITPTR)
419 0 : return ESFalse;
420 :
421 : /* ...and we are not sleeping */
422 1676 : if (scripter_mod.sleep > 0) {
423 :
424 1283 : gettimeofday (&now, NULL);
425 1283 : substract_timeval (&res, &now, &scripter_mod.time);
426 :
427 1283 : elapsed = (unsigned long)res.tv_sec * (unsigned long)1000;
428 1283 : elapsed += (unsigned long)res.tv_usec / (unsigned long)1000;
429 :
430 1283 : if (elapsed >= scripter_mod.sleep) {
431 10 : scripter_mod.sleep = 0;
432 : } else {
433 1273 : return ESFalse;
434 : }
435 : }
436 :
437 : /* ...and we are not waiting EVENT_IND */
438 403 : if (scripter_mod.event_pending)
439 44 : return ESFalse;
440 :
441 359 : return ESTrue;
442 : }
443 :
444 : /* ------------------------------------------------------------------------- */
445 : LOCAL void fetch_ptr2run (const char *dllname, const char *classname)
446 6 : {
447 6 : TestClassDetails *tcd = INITPTR;
448 6 : int clen = 0;
449 : char *tmp;
450 :
451 6 : if (dllname == INITPTR) {
452 0 : errno = EINVAL;
453 0 : SCRIPTER_RTERR ("library name missing");
454 0 : goto EXIT;
455 : }
456 6 : if (strlen (dllname) == 0) {
457 0 : errno = EINVAL;
458 0 : SCRIPTER_RTERR ("library name has 0 length");
459 0 : goto EXIT;
460 : }
461 :
462 : /* 0) Initialize some data */
463 6 : tcd = NEW (TestClassDetails);
464 :
465 : /* 1) Load dll library */
466 6 : tcd->dllhandle_ = tl_open_tc (dllname);
467 6 : if (tcd->dllhandle_ == INITPTR) {
468 0 : tmp = NEW2 (char,
469 : strlen ("Unable to load library ") +
470 : strlen (dllname) + 1);
471 0 : sprintf (tmp, "Unable to load library %s", dllname);
472 0 : SCRIPTER_RTERR_ARG (tmp, dlerror());
473 0 : DELETE (tmp);
474 0 : MIN_WARN ("Unable to load library [%s] because: %s",
475 : dllname, dlerror ());
476 0 : DELETE (tcd);
477 0 : goto EXIT;
478 : }
479 :
480 : /* 2) Fetch pointer to the run function */
481 6 : tcd->runtc_ = dlsym (tcd->dllhandle_, "ts_run_method");
482 6 : if (tcd->runtc_ == NULL) {
483 0 : SCRIPTER_RTERR_ARG ("Unable to resolve ts_run_method",
484 : dlerror ());
485 0 : MIN_ERROR ("Unable to resolve ts_run_method: %s",
486 : dlerror ());
487 0 : DELETE (tcd);
488 0 : goto EXIT;
489 : }
490 :
491 : /* 3) Store mnemonic for that library */
492 6 : clen = strlen (classname);
493 6 : tcd->classname_ = NEW2 (char, clen + 1);
494 6 : memset (tcd->classname_, 0x0, clen + 1);
495 6 : STRCPY (tcd->classname_, classname, clen + 1);
496 :
497 : /* 4) Save data on the list */
498 6 : dl_list_add (tp_handlers, tcd);
499 6 : EXIT:
500 : return;
501 : }
502 :
503 : /* ------------------------------------------------------------------------- */
504 : LOCAL void read_optional_run_params (MinItemParser * mip, ExtraParams * ep)
505 14 : {
506 14 : char *token = INITPTR;
507 14 : int token2 = 0;
508 14 : char *parsing_position = INITPTR;
509 14 : int tmp = 0;
510 14 : TParsingType parsing = ENormalParsing;
511 :
512 14 : if (mip == INITPTR) {
513 0 : SCRIPTER_RTERR ("Item parser argument is missing");
514 0 : goto EXIT;
515 : }
516 14 : if (ep == INITPTR) {
517 0 : SCRIPTER_RTERR ("Extra params argument is missing");
518 0 : goto EXIT;
519 : }
520 :
521 : /* expect parameter */
522 14 : parsing_position = mip->item_skip_and_mark_pos_;
523 14 : tmp = mip_get_next_tagged_int (mip, "expect", &token2);
524 14 : if (tmp == ENOERR) {
525 0 : ep->expect_ = token2;
526 0 : token2 = 0;
527 : } else {
528 14 : ep->expect_ = ENOERR;
529 : }
530 :
531 : /* testid parameter */
532 14 : mip->item_skip_and_mark_pos_ = parsing_position;
533 14 : tmp = mip_get_next_tagged_string (mip, "testid", &token);
534 14 : if (tmp == ENOERR) {
535 5 : if (token != INITPTR) {
536 5 : STRCPY (ep->testid_, token, 128);
537 5 : DELETE (token);
538 5 : token = INITPTR;
539 : }
540 : } else {
541 9 : STRCPY (ep->testid_, "\0", 128);
542 : }
543 :
544 : /* ini parameter */
545 14 : mip->item_skip_and_mark_pos_ = parsing_position;
546 14 : tmp = mip_get_next_tagged_string (mip, "ini", &token);
547 14 : if (tmp == ENOERR) {
548 0 : if (token != INITPTR) {
549 0 : STRCPY (ep->ini_, token, 512);
550 0 : DELETE (token);
551 0 : token = INITPTR;
552 : }
553 : } else {
554 14 : STRCPY (ep->ini_, "\0", 512);
555 : }
556 :
557 : /* category parameter */
558 14 : mip->item_skip_and_mark_pos_ = parsing_position;
559 14 : tmp = mip_get_next_tagged_string (mip, "category", &token);
560 14 : if (tmp == ENOERR) {
561 0 : ep->category_ = get_result_category (token);
562 0 : DELETE (token);
563 0 : token = INITPTR;
564 : }
565 :
566 : /* timeout parameter */
567 14 : mip->item_skip_and_mark_pos_ = parsing_position;
568 14 : tmp = mip_get_next_tagged_string (mip, "timeout", &token);
569 14 : if (tmp == ENOERR) {
570 0 : ep->timeout_ = 0;
571 0 : DELETE (token);
572 0 : token = INITPTR;
573 : }
574 :
575 : /* title parameter */
576 14 : parsing = mip_get_parsing_type (mip);
577 14 : mip_set_parsing_type (mip, EQuoteStyleParsing);
578 14 : mip->item_skip_and_mark_pos_ = parsing_position;
579 14 : tmp = mip_get_next_tagged_string (mip, "title", &token);
580 14 : if (tmp == ENOERR) {
581 7 : if (token != INITPTR) {
582 7 : STRCPY (ep->title_, token, 128);
583 7 : DELETE (token);
584 7 : token = INITPTR;
585 : }
586 : } else {
587 7 : STRCPY (ep->title_, "\0", 128);
588 : }
589 14 : mip_set_parsing_type (mip, parsing);
590 14 : EXIT:
591 : return;
592 : }
593 :
594 : /* ------------------------------------------------------------------------- */
595 : LOCAL void uengine_read_message (int mqid, MsgBuffer * input_buffer)
596 61 : {
597 61 : int retval = 0;
598 :
599 61 : retval = mq_read_message (mqid, getpid ()
600 : , input_buffer);
601 61 : if (retval == -1) {
602 0 : switch (errno) {
603 : case EINTR:
604 0 : MIN_DEBUG ("Reading MQ interrupted by signal");
605 0 : break;
606 :
607 : case EIDRM:
608 0 : SCRIPTER_RTERR("MQ id removed from the system");
609 0 : MIN_FATAL ("MQ id removed from the system");
610 0 : break;
611 :
612 : case E2BIG:
613 0 : MIN_WARN ("Recieved message too big");
614 0 : break;
615 :
616 : case EINVAL:
617 0 : SCRIPTER_RTERR("Invalid value: mq_read_message");
618 0 : MIN_ERROR ("Invalid value: mq_read_message");
619 : break;
620 : }
621 61 : } else if (retval < 8) {
622 : /*ignore too short messages */
623 0 : MIN_NOTICE ("Recieved message is too small");
624 : }
625 :
626 61 : }
627 :
628 : /* ------------------------------------------------------------------------- */
629 : LOCAL void uengine_handle_message (int mqid, const MsgBuffer * msg)
630 61 : {
631 : MsgBuffer out;
632 :
633 61 : switch (msg->type_) {
634 : case MSG_RET:
635 33 : MIN_DEBUG ("Recieved MSG_RET");
636 33 : uengine_handle_ret (mqid, msg->param_, msg->message_,
637 : msg->sender_);
638 33 : break;
639 : case MSG_USR:
640 12 : MIN_DEBUG ("Recieved MSG_USR");
641 : /* Forward message to upper level */
642 12 : memcpy (&out, msg, sizeof (MsgBuffer));
643 12 : out.sender_ = getpid ();
644 12 : out.receiver_ = getppid ();
645 12 : mq_send_message (mqid, &out);
646 :
647 : /* */
648 12 : sched_yield ();
649 :
650 12 : break;
651 : case MSG_EVENT:
652 0 : MIN_DEBUG ("Recieved MSG_EVENT");
653 0 : memcpy (&out, msg, sizeof (MsgBuffer));
654 0 : out.sender_ = getpid ();
655 0 : out.receiver_ = getppid ();
656 0 : mq_send_message (mqid, &out);
657 0 : break;
658 : case MSG_EVENT_IND:
659 5 : MIN_DEBUG ("Recieved MSG_EVENT_IND");
660 5 : uengine_handle_event_ind (mqid, msg);
661 5 : break;
662 : case MSG_END:
663 0 : MIN_DEBUG ("Recieved MSG_END");
664 0 : uengine_handle_end (mqid, msg);
665 0 : break;
666 : case MSG_PAUSE:
667 0 : MIN_DEBUG ("Recieved MSG_PAUSE");
668 0 : uengine_handle_pause (mqid, msg);
669 0 : break;
670 : case MSG_RESUME:
671 0 : MIN_DEBUG ("Recieved MSG_RESUME");
672 0 : uengine_handle_resume (mqid, msg);
673 0 : break;
674 : case MSG_STOP:
675 0 : MIN_DEBUG ("Recieved MSG_STOP");
676 0 : uengine_handle_stop (mqid, msg);
677 0 : break;
678 : case MSG_EXTIF:
679 10 : MIN_DEBUG ("Recieved MSG_EXTIF");
680 10 : uengine_handle_extif (mqid, msg);
681 10 : break;
682 : case MSG_SNDRCV:
683 1 : MIN_DEBUG ("Recieved MSG_SNDRCV");
684 1 : uengine_handle_sndrcv (mqid, msg);
685 1 : break;
686 : default:
687 0 : MIN_WARN ("Unhandled message from %d: to %d, type: %d",
688 : msg->sender_, msg->receiver_, msg->type_);
689 : }
690 :
691 :
692 61 : }
693 :
694 : /* ------------------------------------------------------------------------- */
695 : LOCAL void uengine_handle_ret (int mqid, int param, const char *message,
696 : long sender)
697 33 : {
698 33 : DLListIterator it = DLListNULLIterator;
699 33 : DLListIterator it2 = DLListNULLIterator;
700 33 : int desiredstatus = TP_RUNNING;
701 33 : ScriptedTestProcessDetails *stpd = INITPTR;
702 33 : int *tmp = INITPTR;
703 : int status;
704 : TestCaseResult *tcr;
705 : char tmp2[12];
706 33 : TSBool complete_used=ESFalse;
707 :
708 33 : if (message == INITPTR) {
709 0 : errno = EINVAL;
710 0 : SCRIPTER_RTERR ("empty message");
711 0 : goto EXIT;
712 : }
713 :
714 33 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
715 : , dl_list_tail (scripter_mod.tp_details)
716 : , _findpid, &sender);
717 33 : if (it == DLListNULLIterator) {
718 0 : sprintf (tmp2, "%lu", sender);
719 0 : SCRIPTER_RTERR_ARG ("No test of given pid", tmp2);
720 0 : MIN_WARN ("There is no test of given pid [%d]", sender);
721 0 : goto EXIT;
722 : }
723 33 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
724 :
725 33 : if (stpd->mod_type_ == EDLLTypeNormal) {
726 : /* We have TP created by RUN keyword (Combiner)
727 : * let go back to previous idea and send
728 : * test result to the upper level
729 : */
730 :
731 : /* Check if we are waiting for this test to complete
732 : * if so then restart script execution. */
733 6 : if (scripter_mod.testcomplete != INITPTR &&
734 : !strcmp (scripter_mod.testcomplete,
735 : stpd->options_.testid_)) {
736 0 : complete_used=ESTrue;
737 0 : DELETE (scripter_mod.testcomplete);
738 0 : scripter_mod.testcomplete = INITPTR;
739 : }
740 :
741 : /* set status */
742 6 : stpd->status_ = TP_ENDED;
743 :
744 6 : if(complete_used==ESTrue){
745 0 : test_complete(stpd->options_.testid_);
746 : }
747 :
748 : /* kill TP :) */
749 6 : kill (sender, SIGUSR2);
750 6 : waitpid (sender, &status, 0);
751 :
752 : /* set test result test result is checked
753 : * against expected optional parameter */
754 6 : tcr = NEW (TestCaseResult);
755 6 : if (param == stpd->options_.expect_) {
756 6 : tcr->result_ = TP_PASSED;
757 : } else {
758 0 : tcr->result_ = TP_FAILED;
759 : }
760 6 : update_variables (tcr->result_);
761 :
762 6 : STRCPY (tcr->desc_, message, MaxTestResultDescription);
763 6 : dl_list_add (stpd->tcr_list_, tcr);
764 :
765 : /* Check test result and canceliferror flag */
766 6 : if (param == TP_FAILED
767 : && scripter_mod.canceliferror == ESTrue) {
768 0 : MIN_DEBUG ("Test Failed, canceliferror ON");
769 0 : stpd->status_ = TP_CANCELED;
770 0 : update_variables (TP_NC);
771 0 : scripter_mod.script_finished = ESTrue;
772 : /* Now we have to 'end' rest of the tests */
773 0 : it2 = dl_list_head (scripter_mod.tp_details);
774 : do {
775 0 : it = dl_list_find (it2,
776 : dl_list_tail (scripter_mod.
777 : tp_details)
778 : , _findstatus,
779 : &desiredstatus);
780 :
781 0 : if (it == DLListNULLIterator) {
782 0 : break;
783 : }
784 :
785 : /* set status to cancelled */
786 0 : stpd = (ScriptedTestProcessDetails *)
787 : dl_list_data (it);
788 0 : stpd->status_ = TP_CANCELED;
789 0 : update_variables (TP_NC);
790 : /* kill test process */
791 0 : kill (stpd->pid_, SIGUSR2);
792 0 : waitpid (stpd->pid_, &status, 0);
793 :
794 : /* cause searching is in range [] */
795 0 : it = dl_list_next (it);
796 0 : it2 = it;
797 :
798 0 : } while (it != DLListNULLIterator);
799 : }
800 :
801 : } else {
802 : /* We have TP created by callfunc keyword (Scripter) */
803 :
804 : /* check if the test class has modified scripter variables */
805 27 : if (dl_list_size (variables) > 0) {
806 27 : receive_variables();
807 : }
808 : /* Check result against allowed test result */
809 27 : it = dl_list_find (dl_list_head (stpd->allowed_results_)
810 : , dl_list_tail (stpd->allowed_results_)
811 : , _findallowedresult,
812 : (const void *)¶m);
813 27 : if (it == DLListNULLIterator) {
814 0 : param = TP_FAILED;
815 : } else {
816 27 : param = TP_PASSED;
817 : }
818 27 : update_variables (param);
819 : /* Now we can destroy the list. No need to keep allowed
820 : * result any more. */
821 27 : it = dl_list_head (stpd->allowed_results_);
822 81 : while (it != DLListNULLIterator) {
823 27 : tmp = (int *)dl_list_data (it);
824 27 : DELETE (tmp);
825 27 : dl_list_remove_it (it);
826 27 : it = dl_list_head (stpd->allowed_results_);
827 : }
828 27 : dl_list_free (&stpd->allowed_results_);
829 :
830 27 : scripter_mod.tclass_exec = 0;
831 :
832 : /* Do result reporting stuff */
833 27 : tcr = NEW (TestCaseResult);
834 27 : tcr->result_ = param;
835 27 : STRCPY (tcr->desc_, message, MaxTestResultDescription);
836 :
837 27 : dl_list_add (stpd->tcr_list_, tcr);
838 : }
839 33 : EXIT:
840 : return;
841 : }
842 :
843 : /* ------------------------------------------------------------------------- */
844 : LOCAL void uengine_handle_end (int mqid, const MsgBuffer * msg)
845 0 : {
846 : /* Not needed on this sprint */
847 0 : }
848 :
849 : /* ------------------------------------------------------------------------- */
850 : LOCAL void uengine_handle_pause (int mqid, const MsgBuffer * msg)
851 0 : {
852 : /* Not needed on this sprint */
853 0 : }
854 :
855 : /* ------------------------------------------------------------------------- */
856 : LOCAL void uengine_handle_resume (int mqid, const MsgBuffer * msg)
857 0 : {
858 : /* Not needed on this sprint */
859 0 : }
860 :
861 : /* ------------------------------------------------------------------------- */
862 : LOCAL void uengine_handle_stop (int mqid, const MsgBuffer * msg)
863 0 : {
864 : /* Not needed on this sprint */
865 0 : }
866 :
867 : /* ------------------------------------------------------------------------- */
868 : LOCAL void uengine_handle_extif (int mqid, const MsgBuffer * msg)
869 10 : {
870 10 : switch (msg->extif_msg_type_) {
871 : case EResponseSlave:
872 8 : MIN_DEBUG ("EResponseSlave");
873 8 : uengine_handle_extif_response (msg->param_, msg->special_);
874 8 : break;
875 : case ERemoteSlaveResponse:
876 2 : MIN_DEBUG ("ERemoteSlaveResponse");
877 2 : uengine_handle_extif_remote_response (msg->param_,
878 : msg->special_);
879 2 : break;
880 : default:
881 0 : MIN_WARN ("Unknown EXTIF command response: [%d]",
882 : msg->param_);
883 : }
884 : return;
885 : }
886 :
887 : /* ------------------------------------------------------------------------- */
888 : LOCAL void uengine_handle_extif_response (int result, int caseid)
889 8 : {
890 8 : ScriptedTestProcessDetails *stpd = INITPTR;
891 8 : int *tmp = INITPTR;
892 : /* check if na error occured - if there is an error then
893 : * break script execution, if not then resume it. */
894 8 : if (result != ENOERR) {
895 0 : MIN_WARN ("remote run error: %d", result);
896 0 : SCRIPTER_RTERR ("Remote run error");
897 0 : scripter_mod.extif_pending = ESFalse;
898 :
899 0 : goto EXIT;
900 : }
901 :
902 : /* special field can carry an test id - if > 0
903 : * caseid is > 0 only when response is for REMOTE RUN */
904 8 : if (caseid > 0) {
905 :
906 2 : scripter_mod.extif_remote++;
907 2 : MIN_DEBUG ("scripter_mod.extif_remote=%d",
908 : scripter_mod.extif_remote);
909 :
910 2 : stpd = NEW (ScriptedTestProcessDetails);
911 2 : stpd->tcr_list_ = dl_list_create ();
912 2 : STRCPY (stpd->testclass_, "", 1);
913 2 : stpd->pid_ = 0;
914 2 : STRCPY (stpd->dllname_, "", 1);
915 2 : STRCPY (stpd->cfgfile_, "", 1);
916 2 : stpd->mod_type_ = EDLLTypeNormal;
917 2 : stpd->options_.expect_ = ENOERR;
918 2 : sprintf (stpd->options_.testid_, "%d", caseid); /* caseid */
919 2 : STRCPY (stpd->options_.ini_, "", 1);
920 2 : stpd->options_.category_ = ECategoryNormal;
921 2 : stpd->options_.timeout_ = 0;
922 2 : STRCPY (stpd->options_.title_, "", 1);
923 2 : stpd->status_ = TP_RUNNING;
924 :
925 : /* Handle result allowing. */
926 2 : if (allowedresults == INITPTR) {
927 2 : stpd->allowed_results_ = dl_list_create ();
928 2 : tmp = NEW (int);
929 2 : *tmp = ENOERR;
930 2 : dl_list_add (stpd->allowed_results_, (void *)tmp);
931 : } else {
932 0 : stpd->allowed_results_ = allowedresults;
933 0 : allowedresults = INITPTR;
934 : }
935 :
936 2 : dl_list_add (scripter_mod.tp_details, (void *)stpd);
937 : }
938 :
939 : /* resume execution */
940 8 : scripter_mod.extif_pending = ESFalse;
941 8 : EXIT:
942 : return;
943 : }
944 :
945 : /* ------------------------------------------------------------------------- */
946 : LOCAL void uengine_handle_extif_remote_response (int testresult, int caseid)
947 2 : {
948 2 : DLListIterator it = DLListNULLIterator;
949 : char id[128];
950 2 : ScriptedTestProcessDetails *stpd = INITPTR;
951 : TestCaseResult *tcr;
952 2 : scripter_mod.extif_remote--;
953 2 : MIN_DEBUG ("scripter_mod.extif_remote=%d",
954 : scripter_mod.extif_remote);
955 :
956 2 : sprintf (id, "%d", caseid);
957 :
958 2 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
959 : , dl_list_tail (scripter_mod.tp_details)
960 : , _findid, id);
961 :
962 2 : if (it == DLListNULLIterator) {
963 0 : SCRIPTER_RTERR_ARG ("No test of specified caseid", id);
964 0 : MIN_WARN ("There is no test of specified caseid [%d]", caseid);
965 0 : goto EXIT;
966 : }
967 :
968 2 : update_variables (testresult);
969 :
970 2 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
971 :
972 : /* set status */
973 2 : stpd->status_ = TP_ENDED;
974 :
975 : /* set test result */
976 2 : tcr = NEW (TestCaseResult);
977 2 : tcr->result_ = testresult;
978 2 : STRCPY (tcr->desc_, "", MaxTestResultDescription);
979 2 : dl_list_add (stpd->tcr_list_, tcr);
980 :
981 :
982 :
983 2 : EXIT:
984 : return;
985 : }
986 :
987 : /* ------------------------------------------------------------------------- */
988 : LOCAL void uengine_handle_event_ind (int mqid, const MsgBuffer * msg)
989 5 : {
990 5 : scripter_mod.event_pending = ESFalse;
991 :
992 5 : if (msg->param_ != EventStatOK) {
993 0 : SCRIPTER_RTERR ("Event error");
994 0 : MIN_ERROR ("Event error occured");
995 : }
996 5 : }
997 :
998 : /* ------------------------------------------------------------------------- */
999 : LOCAL void uengine_handle_sndrcv (int mqid, const MsgBuffer * msg)
1000 1 : {
1001 :
1002 1 : if (!strcmp (scripter_mod.expected_var, msg->message_)) {
1003 1 : scripter_mod.extif_pending = ESFalse;
1004 1 : var_assign (msg->message_, msg->desc_);
1005 : } else {
1006 0 : SCRIPTER_RTERR_ARG ("Received unexpected variable",
1007 : msg->message_);
1008 0 : MIN_ERROR ("Expecting variable "
1009 : "%s, received %s",
1010 : scripter_mod.expected_var, msg->message_);
1011 : }
1012 : return;
1013 : }
1014 :
1015 : /* ------------------------------------------------------------------------- */
1016 : LOCAL void update_variables (TPResult res)
1017 36 : {
1018 36 : switch (res) {
1019 : case TP_CRASHED:
1020 0 : var_increment ("CRASH_COUNT");
1021 0 : var_increment ("ERROR_COUNT");
1022 0 : break;
1023 : case TP_TIMEOUTED:
1024 0 : var_increment ("TOUT_COUNT");
1025 0 : var_increment ("ERROR_COUNT");
1026 0 : break;
1027 : case TP_PASSED:
1028 35 : break;
1029 : case TP_FAILED:
1030 0 : var_increment ("FAIL_COUNT");
1031 0 : var_increment ("ERROR_COUNT");
1032 0 : break;
1033 : case TP_NC:
1034 : case TP_LEAVE:
1035 1 : var_increment ("ABORT_COUNT");
1036 1 : var_increment ("ERROR_COUNT");
1037 1 : break;
1038 : default:
1039 0 : SCRIPTER_RTERR ("Unexpected result");
1040 : break;
1041 : }
1042 36 : var_increment ("TOTAL_COUNT");
1043 36 : }
1044 :
1045 : /* ------------------------------------------------------------------------- */
1046 : /*LOCAL void scripter_sigchld_handler( int sig )
1047 : {
1048 : min_info("Scripter Test process received SIGCHLD");
1049 : }*/
1050 : /* ------------------------------------------------------------------------- */
1051 : LOCAL void scripter_sigalrm_handler (int sig)
1052 0 : {
1053 0 : DLListIterator it = DLListNULLIterator;
1054 0 : DLListIterator it2 = DLListNULLIterator;
1055 0 : int desired = TP_RUNNING;
1056 0 : int status = 0;
1057 0 : ScriptedTestProcessDetails *stpd = INITPTR;
1058 :
1059 : /* Timeout! Stop execution and end all ongoing tests */
1060 0 : it2 = dl_list_head (scripter_mod.tp_details);
1061 : do {
1062 : /* find running test */
1063 0 : it = dl_list_find (it2, dl_list_tail (scripter_mod.tp_details)
1064 : , _findstatus, &desired);
1065 :
1066 0 : if (it == DLListNULLIterator) {
1067 0 : break;
1068 : }
1069 :
1070 : /* set status to timeout */
1071 0 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
1072 0 : stpd->status_ = TP_TIMEOUT;
1073 :
1074 : /* kill test process */
1075 0 : kill (stpd->pid_, SIGUSR2);
1076 0 : waitpid (stpd->pid_, &status, 0);
1077 :
1078 : /* cause searching is in range [] */
1079 0 : it = dl_list_next (it);
1080 0 : it2 = it;
1081 0 : } while (it != DLListNULLIterator);
1082 0 : }
1083 :
1084 : /* ------------------------------------------------------------------------- */
1085 : LOCAL int _look4event (const void *a, const void *b)
1086 2 : {
1087 2 : minEventIf *e = (minEventIf *) a;
1088 2 : return strcmp (e->Name (e), (char *)b);
1089 : }
1090 :
1091 : /* ------------------------------------------------------------------------- */
1092 : LOCAL minEventIf *find_event_reqistration (char *eventname)
1093 3 : {
1094 3 : DLListIterator it = DLListNULLIterator;
1095 3 : it = dl_list_find (dl_list_head (scripter_mod.req_events)
1096 : , dl_list_tail (scripter_mod.req_events)
1097 : , _look4event, eventname);
1098 :
1099 3 : if (it == DLListNULLIterator) {
1100 1 : MIN_WARN ("There is no event of given name: [%s]",eventname);
1101 1 : return INITPTR;
1102 : }
1103 2 : return (minEventIf *) dl_list_data (it);
1104 : }
1105 :
1106 : /* ------------------------------------------------------------------------- */
1107 : LOCAL TTestCategory get_result_category (const char *str)
1108 0 : {
1109 0 : TTestCategory retval = ECategoryUnknown;
1110 :
1111 0 : if (str == INITPTR) {
1112 0 : errno = EINVAL;
1113 0 : SCRIPTER_RTERR("no string");
1114 0 : goto EXIT;
1115 : }
1116 :
1117 0 : if (strcmp ("normal", str) == 0) {
1118 0 : retval = ECategoryNormal;
1119 0 : } else if (strcmp ("leave", str) == 0) {
1120 0 : retval = ECategoryLeave;
1121 0 : } else if (strcmp ("panic", str) == 0) {
1122 0 : retval = ECategoryPanic;
1123 0 : } else if (strcmp ("exception", str) == 0) {
1124 0 : retval = ECategoryException;
1125 0 : } else if (strcmp ("timeout", str) == 0) {
1126 0 : retval = ECategoryTimeout;
1127 : }
1128 0 : EXIT:
1129 0 : return retval;
1130 : }
1131 :
1132 : /* ------------------------------------------------------------------------- */
1133 : LOCAL ScriptVar *var_find (const char *varname)
1134 1221 : {
1135 : DLListIterator it;
1136 : ScriptVar *var;
1137 :
1138 1221 : it = dl_list_head (variables);
1139 6593 : while (it != INITPTR) {
1140 4387 : var = dl_list_data (it);
1141 4387 : if (!strcmp (var->name_, varname)) {
1142 236 : return var;
1143 : }
1144 4151 : it = dl_list_next (it);
1145 : }
1146 985 : return INITPTR;
1147 : }
1148 :
1149 : /* ------------------------------------------------------------------------- */
1150 : LOCAL const char *var_value (const char *varname)
1151 234 : {
1152 : ScriptVar *var;
1153 :
1154 234 : var = var_find (varname);
1155 234 : if (var != INITPTR) {
1156 13 : if (var->initialized_ == ESFalse) {
1157 0 : MIN_WARN ("variable %s not initialized", varname);
1158 0 : return "UNINITIALIZED";
1159 : }
1160 13 : return var->value_;
1161 : }
1162 :
1163 221 : return varname;
1164 : }
1165 :
1166 : /* ------------------------------------------------------------------------- */
1167 : LOCAL void var_assign (const char *varname, const char *varval)
1168 184 : {
1169 : ScriptVar *var;
1170 :
1171 184 : var = var_find (varname);
1172 184 : if (var != INITPTR) {
1173 184 : var->initialized_ = ESTrue;
1174 184 : if (var->value_ != INITPTR)
1175 184 : DELETE (var->value_);
1176 184 : var->value_ = NEW2 (char, strlen (varval) + 1);
1177 184 : STRCPY (var->value_, varval, strlen (varval) + 1);
1178 184 : MIN_DEBUG ("%s=%s", varname, varval);
1179 : } else {
1180 0 : SCRIPTER_RTERR_ARG ("Trying to assign undeclared variable",
1181 : varname);
1182 0 : MIN_WARN ("Trying to assign undeclared variable %s",
1183 : varname);
1184 : }
1185 :
1186 : return;
1187 : }
1188 :
1189 : /* ------------------------------------------------------------------------- */
1190 : LOCAL void var_increment (const char *varname)
1191 38 : {
1192 : ScriptVar *var;
1193 : long intval;
1194 :
1195 38 : var = var_find (varname);
1196 38 : if (var == INITPTR || var->initialized_ == ESFalse) {
1197 0 : SCRIPTER_RTERR_ARG ("Trying to increment undeclared variable",
1198 : varname);
1199 :
1200 : }
1201 38 : intval = strtol (var->value_, NULL, 10);
1202 38 : DELETE (var->value_);
1203 38 : intval ++;
1204 38 : var->value_ = NEW2 (char, 32);
1205 38 : sprintf (var->value_, "%ld", intval);
1206 :
1207 : return;
1208 : }
1209 :
1210 :
1211 : /* ------------------------------------------------------------------------- */
1212 : LOCAL void send_variables ()
1213 27 : {
1214 : DLListIterator it;
1215 : ScriptVar *var;
1216 : Text *vars;
1217 27 : void *sh_mem_handle = NULL, *tmp;
1218 :
1219 27 : vars = tx_create (INITPTR);
1220 :
1221 236 : for (it = dl_list_head(variables); it != INITPTR;
1222 182 : it = dl_list_next(it)) {
1223 182 : var = dl_list_data (it);
1224 182 : tx_c_append (vars, var->name_);
1225 182 : if (var->initialized_) {
1226 182 : tx_c_append (vars, "=");
1227 182 : tx_c_append (vars, var->value_);
1228 : }
1229 182 : tx_c_append (vars, " ");
1230 : }
1231 :
1232 27 : sh_mem_handle = sm_attach (scripter_mod.shm_id);
1233 :
1234 27 : if ((vars->size_ + sizeof (unsigned int)) >
1235 : sm_get_segsz (scripter_mod.shm_id)) {
1236 0 : SCRIPTER_RTERR ("Variables do not fit into SHM");
1237 0 : tx_destroy (&vars);
1238 0 : return;
1239 : }
1240 :
1241 27 : sm_write (sh_mem_handle,
1242 : (void *)&vars->size_,
1243 : sizeof (unsigned int));
1244 27 : tmp = sh_mem_handle + sizeof (unsigned int);
1245 27 : sm_write (tmp,
1246 : (void *)(tx_share_buf (vars)),
1247 : vars->size_);
1248 :
1249 27 : MIN_DEBUG ("SENT VARIABLES: %s", tx_share_buf(vars));
1250 27 : sm_detach (sh_mem_handle);
1251 :
1252 27 : tx_destroy (&vars);
1253 : }
1254 : /* ------------------------------------------------------------------------- */
1255 : LOCAL void receive_variables ()
1256 27 : {
1257 : void *shmaddr;
1258 : unsigned int size;
1259 27 : char *var_buff = INITPTR, *variable_str, *p;
1260 : MinItemParser *mip;
1261 :
1262 27 : shmaddr = sm_attach (scripter_mod.shm_id);
1263 27 : if (shmaddr == INITPTR) {
1264 0 : SCRIPTER_RTERR ("Could not attach to shared memory segment");
1265 0 : return;
1266 : }
1267 :
1268 27 : if ( sm_read (shmaddr, &size, sizeof (unsigned int)) != ENOERR) {
1269 0 : SCRIPTER_RTERR ("Read from shared memory segment failed");
1270 0 : goto exit;
1271 27 : } else if (size == 0) {
1272 0 : goto exit;
1273 : }
1274 : /*
1275 : ** Read the variable buffer from shared memory
1276 : */
1277 27 : var_buff = NEW2 (char, size + 1);
1278 27 : sm_read (shmaddr + sizeof (unsigned int), var_buff, size);
1279 27 : var_buff [size] = '\0';
1280 27 : MIN_DEBUG ("RECEIVED from test class: %s", var_buff);
1281 : /*
1282 : ** Create Item Parser for variable parsing
1283 : */
1284 27 : mip = mip_create (var_buff, 0, size);
1285 27 : if (mip == INITPTR) {
1286 0 : SCRIPTER_RTERR ("Failed to create item parser from variables");
1287 0 : goto exit;
1288 : }
1289 : /*
1290 : ** Parse the variables and save them to variable list
1291 : */
1292 27 : mip_get_string (mip, INITPTR, &variable_str);
1293 209 : while (variable_str != INITPTR) {
1294 182 : if ((p = strrchr (variable_str, '=')) == NULL) {
1295 0 : if (var_find (variable_str) == INITPTR) {
1296 0 : SCRIPTER_RTERR_ARG ("Undeclared variable from"
1297 : "testclass", variable_str);
1298 0 : DELETE (variable_str);
1299 0 : goto exit;
1300 : }
1301 : } else {
1302 : /*
1303 : ** test class may have set the variable
1304 : */
1305 182 : *p = '\0';
1306 182 : p++;
1307 :
1308 182 : if (strlen (p) > 0) {
1309 : /*
1310 : ** try to assign the new value
1311 : */
1312 182 : var_assign (variable_str, p);
1313 182 : DELETE (variable_str);
1314 0 : } else if (var_find (variable_str) == INITPTR) {
1315 : /*
1316 : ** Check that the variable is declared
1317 : */
1318 0 : SCRIPTER_RTERR_ARG ("undeclared variable from "
1319 : "testclass", variable_str);
1320 0 : DELETE (variable_str);
1321 0 : goto exit;
1322 :
1323 : }
1324 : }
1325 182 : if (mip_get_next_string (mip, &variable_str) != ENOERR)
1326 27 : break;
1327 : }
1328 :
1329 27 : exit:
1330 27 : if (mip != INITPTR)
1331 27 : mip_destroy (&mip);
1332 27 : if (var_buff != INITPTR)
1333 27 : DELETE (var_buff);
1334 :
1335 27 : sm_detach (shmaddr);
1336 :
1337 27 : return;
1338 : }
1339 :
1340 : /* ------------------------------------------------------------------------- */
1341 : LOCAL void scripter_final_verdict (DLList * tp_details, TestCaseResult * tcr)
1342 24 : {
1343 : ScriptedTestProcessDetails *stpd;
1344 : DLListIterator tpit, reit;
1345 : TestCaseResult *res;
1346 : int num_fail, num_ok, cancelled;
1347 24 : num_fail = num_ok = cancelled = 0;
1348 : char *result_str [] = {"CRASHED",
1349 : "TIMEOUTED",
1350 : "TP_PASSED",
1351 : "FAILED",
1352 : "NOT COMPLETE",
1353 24 : "LEFT"};
1354 :
1355 24 : for (tpit = dl_list_head (tp_details);
1356 39 : tpit != DLListNULLIterator; tpit = dl_list_next (tpit)) {
1357 15 : stpd = dl_list_data (tpit);
1358 15 : switch (stpd->status_) {
1359 : case TP_ENDED:
1360 : case TP_ABORTED:
1361 : break;
1362 : case TP_CANCELED:
1363 0 : snprintf (tcr->desc_,
1364 : MaxTestResultDescription - 1,
1365 : "Run %s(%d) cancelled ",
1366 : stpd->dllname_,
1367 : stpd->tc_id_
1368 : );
1369 0 : cancelled = 1;
1370 0 : continue;
1371 : default:
1372 0 : MIN_WARN ("Unexpected status of scripter "
1373 : "test case %d", stpd->status_);
1374 0 : snprintf (tcr->desc_,
1375 : MaxTestResultDescription - 1,
1376 : "Unexpected status (%d) of scripter"
1377 : "test case", stpd->status_);
1378 :
1379 0 : num_fail++;
1380 0 : continue;
1381 :
1382 : }
1383 15 : for (reit = dl_list_head (stpd->tcr_list_);
1384 50 : reit != DLListNULLIterator; reit = dl_list_next (reit)) {
1385 35 : res = dl_list_data (reit);
1386 35 : switch (res->result_) {
1387 : case TP_CRASHED:
1388 : case TP_FAILED:
1389 : case TP_TIMEOUTED:
1390 : case TP_LEAVE:
1391 0 : num_fail++;
1392 0 : if (strlen (tcr->desc_) > 0)
1393 0 : break;
1394 0 : if (stpd->mod_type_ == EDLLTypeClass)
1395 0 : snprintf (tcr->desc_,
1396 : MaxTestResultDescription - 1,
1397 : "Test Method call \"%s.%s\""
1398 : " %s",
1399 : stpd->testclass_,
1400 : res->desc_,
1401 : result_str
1402 : [res->result_ + 2]);
1403 : else {
1404 0 : snprintf (tcr->desc_,
1405 : MaxTestResultDescription - 1,
1406 : "Run %s(%d) %s: %s ",
1407 : stpd->dllname_,
1408 : stpd->tc_id_,
1409 : result_str
1410 : [res->result_ + 2],
1411 : res->desc_
1412 : );
1413 : }
1414 0 : break;
1415 : case TP_PASSED:
1416 35 : num_ok++;
1417 35 : break;
1418 : case TP_NC:
1419 0 : MIN_DEBUG ("TP_NC .. unxepected result code");
1420 0 : break;
1421 : num_fail++;
1422 : break;
1423 : default:
1424 0 : MIN_DEBUG ("unknown result code %d",
1425 : tcr->result_);
1426 : break;
1427 : }
1428 : }
1429 : }
1430 :
1431 24 : if (cancelled) {
1432 0 : tcr->result_ = TP_NC;
1433 24 : } else if (num_fail > 0) {
1434 0 : if (num_fail > 1)
1435 0 : sprintf (tcr->desc_, "%s (%d other errors/failures)",
1436 : tcr->desc_, num_fail - 1);
1437 0 : tcr->result_ = TP_FAILED;
1438 : } else {
1439 24 : tcr->result_ = TP_PASSED;
1440 24 : sprintf (tcr->desc_, "Scripted test case passed");
1441 : }
1442 24 : MIN_DEBUG ("returning from scripter with desc %s",
1443 : tcr->desc_);
1444 :
1445 24 : }
1446 :
1447 :
1448 : /* ------------------------------------------------------------------------- */
1449 : /* ======================== FUNCTIONS ====================================== */
1450 : /* ------------------------------------------------------------------------- */
1451 : int substract_timeval (struct timeval *result, struct timeval *x,
1452 : struct timeval *y)
1453 1283 : {
1454 : /* Perform the carry for the later subtraction by updating y. */
1455 1283 : if (x->tv_usec < y->tv_usec) {
1456 : int nsec =
1457 19 : (y->tv_usec - x->tv_usec) / 1000000 + 1;
1458 19 : y->tv_usec -= 1000000 * nsec;
1459 19 : y->tv_sec += nsec;
1460 : }
1461 1283 : if (x->tv_usec - y->tv_usec > 1000000) {
1462 19 : int nsec = (x->tv_usec - y->tv_usec) / 1000000;
1463 19 : y->tv_usec += 1000000 * nsec;
1464 19 : y->tv_sec -= nsec;
1465 : }
1466 :
1467 : /* Compute the time remaining to wait.
1468 : * tv_usec is certainly positive. */
1469 1283 : result->tv_sec = x->tv_sec - y->tv_sec;
1470 1283 : result->tv_usec = x->tv_usec - y->tv_usec;
1471 :
1472 : /* Return 1 if result is negative. */
1473 1283 : return x->tv_sec < y->tv_sec;
1474 : }
1475 :
1476 : /* ------------------------------------------------------------------------- */
1477 : int add_timeval (struct timeval *result, struct timeval *x, struct timeval *y)
1478 0 : {
1479 : /* add it */
1480 0 : result->tv_usec = x->tv_usec + y->tv_usec;
1481 0 : result->tv_sec = x->tv_sec + y->tv_sec;
1482 :
1483 : /* round it */
1484 0 : while (result->tv_usec < 1000000) {
1485 0 : result->tv_usec -= 1000000;
1486 0 : result->tv_sec++;
1487 : }
1488 :
1489 :
1490 0 : return 1;
1491 : }
1492 :
1493 : /* ------------------------------------------------------------------------- */
1494 : int testclass_create (filename_t dllName, char *className)
1495 15 : {
1496 15 : int retval = ENOERR;
1497 15 : pid_t pid = -1;
1498 15 : char *dllpath = NEW2 (char, strlen (dllName) + 3 + 1);
1499 15 : ScriptedTestProcessDetails *stpd = INITPTR;
1500 : MsgBuffer input_buffer;
1501 :
1502 15 : if (strlen (dllName) == 0) {
1503 0 : errno = EINVAL;
1504 0 : retval = -1;
1505 0 : SCRIPTER_RTERR ("Library is 0 lenght");
1506 0 : goto EXIT;
1507 : }
1508 15 : if (className == INITPTR) {
1509 0 : errno = EINVAL;
1510 0 : SCRIPTER_RTERR ("class name missing");
1511 0 : retval = -1;
1512 0 : goto EXIT;
1513 : }
1514 :
1515 15 : STRCPY (dllpath, dllName, strlen (dllName));
1516 15 : STRCPY (&dllpath[strlen (dllName)], ".so", 4);
1517 :
1518 15 : pid = fork ();
1519 15 : if (pid == 0) {
1520 : /* Child process, lets enter event loop */
1521 6 : stprun = ESTrue;
1522 6 : sched_yield ();
1523 6 : min_log_open ("ScriptedTP", 3);
1524 6 : mq_init_buffer ();
1525 6 : signal (SIGUSR2, stp_handle_sigusr2);
1526 :
1527 6 : fetch_ptr2run (dllpath, className);
1528 :
1529 240 : while (stprun) {
1530 228 : if (mq_peek_message (scripter_mod.mqid, getpid())) {
1531 27 : retval = mq_read_message (scripter_mod.mqid,
1532 : getpid ()
1533 : , &input_buffer);
1534 27 : stp_handle_message (&input_buffer);
1535 : }
1536 228 : usleep (10000);
1537 : }
1538 6 : stp_exit();
1539 9 : } else if (pid > 0) {
1540 : /* TestProcess details are stored on the list */
1541 9 : MIN_INFO ("Scripted Test Process created, pid: %d",getpid());
1542 9 : stpd = NEW (ScriptedTestProcessDetails);
1543 9 : stpd->tcr_list_ = dl_list_create ();
1544 9 : stpd->pid_ = pid;
1545 9 : stpd->mod_type_ = EDLLTypeClass;
1546 9 : stpd->status_ = TP_NONE;
1547 9 : STRCPY (stpd->testclass_, className, 128);
1548 9 : STRCPY (stpd->dllname_, dllpath, MaxFileName);
1549 9 : dl_list_add (scripter_mod.tp_details, (void *)stpd);
1550 : } else {
1551 : /* Error */
1552 0 : SCRIPTER_RTERR ("Cannot create Scripted Test Process!");
1553 0 : MIN_ERROR ("Cannot create Scripted Test Process!");
1554 : }
1555 9 : DELETE (dllpath);
1556 9 : EXIT:
1557 9 : return retval;
1558 : }
1559 :
1560 : /* ------------------------------------------------------------------------- */
1561 : int testclass_call_function (char *className, MinItemParser * mip)
1562 27 : {
1563 27 : int retval = ENOERR;
1564 27 : int *tmp = INITPTR;
1565 27 : DLListIterator it = DLListNULLIterator;
1566 27 : ScriptedTestProcessDetails *stpd = INITPTR;
1567 : MsgBuffer msg;
1568 27 : char *token = INITPTR;
1569 :
1570 27 : memset(&msg, 0x0, sizeof(MsgBuffer));
1571 :
1572 27 : if (className == INITPTR || strlen (className) == 0) {
1573 0 : errno = EINVAL;
1574 0 : SCRIPTER_RTERR ("class name missing");
1575 0 : retval = -1;
1576 0 : goto EXIT;
1577 : }
1578 :
1579 : /* 1) look for classname on list */
1580 :
1581 27 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
1582 : , dl_list_tail (scripter_mod.tp_details)
1583 : , _findclass, (void *)className);
1584 :
1585 27 : if (it == DLListNULLIterator) {
1586 0 : errno = ENODATA;
1587 0 : retval = -1;
1588 0 : SCRIPTER_RTERR_ARG ("Class not found on list", className);
1589 0 : MIN_ERROR ("Class not found on list [%s]", className);
1590 0 : goto EXIT;
1591 : }
1592 :
1593 27 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
1594 :
1595 : /* 2) Fill msg structure with data */
1596 27 : msg.receiver_ = stpd->pid_;
1597 27 : msg.sender_ = getpid ();
1598 27 : msg.type_ = MSG_RUN;
1599 27 : msg.param_ = 0;
1600 :
1601 27 : msg.desc_[0] = '\0';
1602 27 : if (dl_list_size (variables) == 0) {
1603 0 : STRCPY (msg.desc_, mip->item_skip_and_mark_pos_, MaxDescSize);
1604 0 : if (msg.desc_ [MaxDescSize - 1] != '\0' &&
1605 : msg.desc_ [MaxDescSize - 1] != 0x0){
1606 0 : SCRIPTER_RTERR_ARG ("Method call too long", className);
1607 0 : msg.desc_[MaxDescSize-1] = '\0';
1608 : }
1609 : } else {
1610 97 : while (mip_get_next_string (mip, &token) == ENOERR) {
1611 43 : if (strlen (msg.desc_) + strlen (var_value (token))
1612 : >= MaxDescSize) {
1613 0 : SCRIPTER_RTERR_ARG ("Method call too long",
1614 : className);
1615 0 : msg.desc_[MaxDescSize-1] = '\0';
1616 :
1617 : } else
1618 43 : sprintf (msg.desc_, "%s %s", msg.desc_,
1619 : var_value (token));
1620 : }
1621 27 : DELETE (token);
1622 27 : send_variables ();
1623 27 : msg.special_ = scripter_mod.shm_id;
1624 : }
1625 :
1626 27 : STRCPY (msg.message_, className, MaxMsgSize);
1627 27 : msg.special_ = 0;
1628 : /* 3) Handle result allowing. */
1629 27 : if (allowedresults == INITPTR) {
1630 27 : stpd->allowed_results_ = dl_list_create ();
1631 27 : tmp = NEW (int);
1632 27 : *tmp = ENOERR;
1633 27 : dl_list_add (stpd->allowed_results_, (void *)tmp);
1634 : } else {
1635 0 : stpd->allowed_results_ = allowedresults;
1636 0 : allowedresults = INITPTR;
1637 : }
1638 :
1639 : /* 4) send MSG_RUN command */
1640 27 : mq_send_message (scripter_mod.mqid, &msg);
1641 :
1642 : /* 5) Block the script execution until we get result back */
1643 27 : scripter_mod.tclass_exec = 1;
1644 27 : EXIT:
1645 27 : return retval;
1646 : }
1647 :
1648 : /* ------------------------------------------------------------------------- */
1649 : int test_run (const char *modulename, const char *configfile, unsigned int id,
1650 : MinItemParser * mip)
1651 14 : {
1652 14 : ScriptedTestProcessDetails *stpd = INITPTR;
1653 14 : int retval = ENOERR;
1654 14 : int tmp = 0;
1655 : test_libl_t testlib;
1656 14 : DLList *cases = INITPTR;
1657 14 : DLListIterator it = DLListNULLIterator;
1658 : struct sigaction pause_action;
1659 :
1660 14 : TestCaseInfo *tci = INITPTR;
1661 : TestCaseResult tcr;
1662 14 : if (modulename == INITPTR) {
1663 0 : errno = EINVAL;
1664 0 : retval = -1;
1665 0 : goto EXIT;
1666 : }
1667 14 : if (configfile == INITPTR) {
1668 0 : errno = EINVAL;
1669 0 : retval = -1;
1670 0 : goto EXIT;
1671 : }
1672 14 : if (mip == INITPTR) {
1673 0 : errno = EINVAL;
1674 0 : retval = -1;
1675 0 : goto EXIT;
1676 : }
1677 :
1678 14 : stpd = NEW (ScriptedTestProcessDetails);
1679 14 : stpd->tcr_list_ = dl_list_create ();
1680 :
1681 : /* 1) Fetch possible optional parameters. */
1682 14 : read_optional_run_params (mip, &stpd->options_);
1683 :
1684 14 : testlib.test_library_ = tl_open_tc (modulename);
1685 14 : strncpy (testlib.fname_, modulename, 255);
1686 14 : testlib.get_cases_fun_ = (ptr2case) dlsym (testlib.test_library_,
1687 : "tm_get_test_cases");
1688 14 : testlib.run_case_fun_ = (ptr2run) dlsym (testlib.test_library_,
1689 : "tm_run_test_case");
1690 :
1691 14 : if (tl_is_ok (&testlib) == 0) {
1692 0 : retval = -1;
1693 0 : SCRIPTER_RTERR_ARG ("Error opening", modulename);
1694 0 : goto EXIT;
1695 : }
1696 : /* Now we can execute a test. If test case title is
1697 : * specified then we have to use it, otherwise the
1698 : * id can be used */
1699 14 : if (strlen (stpd->options_.title_) > 0) {
1700 : /* Use title, so first we have to find out
1701 : * what is the id of the case of given name. */
1702 7 : cases = dl_list_create ();
1703 7 : testlib.get_cases_fun_ (configfile, &cases);
1704 7 : it = dl_list_head (cases);
1705 7 : id = 1;
1706 21 : while (it != DLListNULLIterator) {
1707 14 : tci = (TestCaseInfo *) dl_list_data (it);
1708 14 : tmp = strcmp (tci->name_, stpd->options_.title_);
1709 14 : if (tmp == 0) {
1710 7 : break;
1711 : }
1712 7 : it = dl_list_next (it);
1713 7 : id++;
1714 : }
1715 7 : dl_list_free_data (&cases);
1716 7 : dl_list_free (&cases);
1717 : }
1718 :
1719 : /* 3) Run a test */
1720 14 : stpd->pid_ = fork ();
1721 14 : if (stpd->pid_ > 0) {
1722 : /* Parent */
1723 8 : STRCPY (stpd->testclass_, "\0", 1);
1724 8 : STRCPY (stpd->dllname_, modulename, MaxFileName);
1725 8 : STRCPY (stpd->cfgfile_, configfile, MaxFileName);
1726 8 : stpd->tc_id_ = id;
1727 8 : stpd->mod_type_ = EDLLTypeNormal;
1728 8 : stpd->status_ = TP_RUNNING;
1729 8 : scripter_mod.testcomplete = INITPTR;
1730 8 : dl_list_add (scripter_mod.tp_details, (void *)stpd);
1731 6 : } else if (stpd->pid_ == 0) {
1732 : /* Child */
1733 6 : ctprun = ESTrue;
1734 6 : min_log_open ("Combined Test Process", 3);
1735 6 : MIN_INFO ("Combined Test Process created, pid: %d",getpid());
1736 6 : mq_init_buffer ();
1737 6 : sched_yield ();
1738 6 : signal (SIGUSR2, ctp_handle_sigusr2);
1739 :
1740 6 : pause_action.sa_sigaction = ctp_hande_sigtstp;
1741 6 : sigfillset (&pause_action.sa_mask);
1742 6 : pause_action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
1743 6 : sigaction (SIGTSTP, &pause_action, NULL);
1744 6 : testlib.run_case_fun_ (id, configfile, &tcr);
1745 6 : mq_send_message2 (scripter_mod.mqid, getppid ()
1746 : , MSG_RET, tcr.result_, tcr.desc_);
1747 27 : while (ctprun) {
1748 15 : usleep (10000);
1749 : } /* Wait for death */
1750 : /* resend buffered, flush message buffer */
1751 6 : mq_resend_buffered ();
1752 6 : mq_flush_msg_buffer ();
1753 : /* At the end exit gracefully. */
1754 6 : exit (TP_EXIT_SUCCESS);
1755 : } else {
1756 0 : SCRIPTER_RTERR ("Test Process NOT created");
1757 0 : MIN_ERROR ("Combined Test Process NOT created");
1758 0 : goto EXIT;
1759 : }
1760 :
1761 8 : EXIT:
1762 8 : return retval;
1763 : }
1764 :
1765 : /* ------------------------------------------------------------------------- */
1766 : int testclass_destroy (char *className)
1767 6 : {
1768 : DLListIterator it;
1769 6 : int retval = ENOERR;
1770 6 : ScriptedTestProcessDetails *stpd = INITPTR;
1771 :
1772 6 : if (className == INITPTR) {
1773 0 : errno = EINVAL;
1774 0 : SCRIPTER_RTERR ("No class name");
1775 0 : goto EXIT;
1776 : }
1777 6 : if (strlen (className) == 0) {
1778 0 : errno = EINVAL;
1779 0 : SCRIPTER_RTERR ("Class name has 0 lenght");
1780 0 : retval = -1;
1781 0 : goto EXIT;
1782 : }
1783 :
1784 : /* clean-up code */
1785 6 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
1786 : , dl_list_tail (scripter_mod.tp_details)
1787 : , _findclass, (void *)className);
1788 6 : if (it == DLListNULLIterator) {
1789 0 : errno = ENODATA;
1790 0 : retval = -1;
1791 0 : SCRIPTER_RTERR_ARG("Class not found on list]", className);
1792 0 : MIN_ERROR ("Class not found on list");
1793 0 : goto EXIT;
1794 : }
1795 :
1796 6 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
1797 :
1798 6 : stpd->status_ = TP_ENDED;
1799 6 : retval = kill (stpd->pid_, SIGUSR2);
1800 6 : if (retval == -1)
1801 0 : MIN_WARN ("Cannot kill %d", stpd->pid_);
1802 : else
1803 6 : MIN_DEBUG ("Killed %d", stpd->pid_);
1804 6 : sleep (1);
1805 :
1806 6 : EXIT:
1807 6 : return retval;
1808 : }
1809 :
1810 : /* ------------------------------------------------------------------------- */
1811 : int event_request (char *eventname, int is_state)
1812 1 : {
1813 1 : int retval = ENOERR;
1814 : minEventIf *event;
1815 :
1816 : /*
1817 : ** We can't be registered for the same event more than once
1818 : */
1819 1 : event = find_event_reqistration (eventname);
1820 1 : if (event != INITPTR) {
1821 0 : SCRIPTER_RTERR_ARG ("Process already registered for event",
1822 : eventname);
1823 0 : MIN_NOTICE ("Process already registered for event %s",
1824 : eventname);
1825 0 : return -1;
1826 : }
1827 :
1828 : /*
1829 : ** Create and request the event
1830 : */
1831 1 : event =
1832 : min_event_create (eventname, is_state ? EState : EIndication);
1833 1 : event->dont_block_ = ESTrue;
1834 1 : scripter_mod.event_pending = ESTrue;
1835 1 : event->SetType (event, EReqEvent);
1836 1 : Event (event);
1837 :
1838 : /*
1839 : ** Add event to the local list of requested event or destroy
1840 : */
1841 1 : dl_list_add (scripter_mod.req_events, event);
1842 1 : retval = ENOERR;
1843 :
1844 1 : return retval;
1845 : }
1846 :
1847 : /* ------------------------------------------------------------------------- */
1848 : int event_wait (char *eventname)
1849 1 : {
1850 1 : int retval = ENOERR;
1851 : minEventIf *event;
1852 :
1853 : /*
1854 : ** We must be registered for the event in order to wait
1855 : */
1856 1 : event = find_event_reqistration (eventname);
1857 1 : if (event == INITPTR) {
1858 0 : SCRIPTER_RTERR_ARG ("No registration for event", eventname);
1859 0 : MIN_WARN ("No registarion for event %s", eventname);
1860 0 : return -1;
1861 : }
1862 :
1863 : /*
1864 : ** Wait for the event
1865 : */
1866 1 : event->SetType (event, EWaitEvent);
1867 1 : scripter_mod.event_pending = ESTrue;
1868 1 : Event (event);
1869 :
1870 1 : if (event->event_status_ == EventStatOK) {
1871 1 : retval = ENOERR;
1872 : } else {
1873 0 : SCRIPTER_RTERR_ARG ("Event() returned with error", eventname);
1874 0 : MIN_WARN ("Event():%s returned with error", eventname);
1875 0 : retval = -1;
1876 : }
1877 1 : return retval;
1878 : }
1879 :
1880 : /* ------------------------------------------------------------------------- */
1881 : int event_release (char *eventname)
1882 1 : {
1883 1 : int retval = ENOERR;
1884 : minEventIf *event;
1885 :
1886 : /*
1887 : ** We must be registered for the event in order release it
1888 : */
1889 1 : event = find_event_reqistration (eventname);
1890 1 : if (event == INITPTR) {
1891 0 : SCRIPTER_RTERR_ARG ("No registration for event %s", eventname);
1892 0 : MIN_WARN ("No registration for event %s", eventname);
1893 0 : return -1;
1894 : }
1895 :
1896 : /*
1897 : ** Release the event
1898 : */
1899 1 : event->SetType (event, ERelEvent);
1900 1 : scripter_mod.event_pending = ESTrue;
1901 1 : Event (event);
1902 :
1903 1 : if (event->event_status_ == EventStatOK) {
1904 1 : retval = ENOERR;
1905 : } else {
1906 0 : SCRIPTER_RTERR_ARG ("Event() returned with error", eventname);
1907 0 : MIN_WARN (" Event():%s returned with error", eventname);
1908 0 : retval = -1;
1909 : }
1910 :
1911 1 : return retval;
1912 : }
1913 :
1914 : /* ------------------------------------------------------------------------- */
1915 : int event_set (char *eventname, int is_state)
1916 1 : {
1917 1 : int retval = ENOERR;
1918 : minEventIf *event;
1919 1 : event =
1920 : min_event_create (eventname, is_state ? EState : EIndication);
1921 1 : event->dont_block_ = ESTrue;
1922 1 : event->SetType (event, ESetEvent);
1923 1 : scripter_mod.event_pending = ESTrue;
1924 1 : Event (event);
1925 1 : if (event->event_status_ == EventStatOK) {
1926 1 : retval = ENOERR;
1927 : } else {
1928 0 : SCRIPTER_RTERR_ARG ("Event() returned with error", eventname);
1929 0 : MIN_WARN ("Event():%s returned with error", eventname);
1930 0 : retval = -1;
1931 : }
1932 :
1933 1 : min_event_destroy (event);
1934 :
1935 1 : return retval;
1936 : }
1937 :
1938 : /* ------------------------------------------------------------------------- */
1939 : int event_unset (char *eventname)
1940 1 : {
1941 1 : int retval = ENOERR;
1942 : minEventIf *event;
1943 :
1944 1 : event = min_event_create (eventname, EState);
1945 1 : event->dont_block_ = ESTrue;
1946 1 : event->SetType (event, EUnsetEvent);
1947 1 : scripter_mod.event_pending = ESTrue;
1948 1 : Event (event);
1949 1 : if (event->event_status_ == EventStatOK) {
1950 1 : retval = ENOERR;
1951 : } else {
1952 0 : SCRIPTER_RTERR_ARG ("Event() returned with error", eventname);
1953 0 : MIN_WARN ("Event():%s returned with error", eventname);
1954 0 : retval = -1;
1955 : }
1956 :
1957 1 : min_event_destroy (event);
1958 :
1959 1 : return retval;
1960 : }
1961 :
1962 : /* ------------------------------------------------------------------------- */
1963 : int script_finish (void)
1964 24 : {
1965 24 : int retval = ENOERR;
1966 24 : scripter_mod.script_finished = 1;
1967 24 : return retval;
1968 : }
1969 :
1970 : /* ------------------------------------------------------------------------- */
1971 : int tm_run_test_case (unsigned int id, const char *cfg_file,
1972 : TestCaseResult * result)
1973 39 : {
1974 39 : int retval = ENOERR;
1975 39 : MinParser *sp = INITPTR;
1976 39 : DLListIterator prev_it, it = DLListNULLIterator;
1977 39 : MinSectionParser *msp = INITPTR;
1978 39 : TSBool msg_pending = ESFalse;
1979 39 : pid_t pid = getpid ();
1980 39 : char *path = INITPTR;
1981 39 : char *c = INITPTR;
1982 : MsgBuffer input_buffer;
1983 : ScriptVar *var;
1984 : ScriptedTestProcessDetails *stpd;
1985 : Text *cfgdefault;
1986 39 : char *dir = INITPTR;
1987 39 : char *file = INITPTR;
1988 :
1989 39 : if (cfg_file == INITPTR) {
1990 0 : errno = EINVAL;
1991 0 : retval = -1;
1992 0 : SCRIPTER_RTERR("config file missing");
1993 0 : goto EXIT;
1994 : }
1995 39 : if (result == INITPTR) {
1996 0 : errno = EINVAL;
1997 0 : SCRIPTER_RTERR("result argument missing");
1998 0 : retval = -1;
1999 0 : goto EXIT;
2000 : }
2001 39 : if (id < 1) {
2002 0 : errno = EINVAL;
2003 0 : SCRIPTER_RTERR("invalid test case id");
2004 0 : retval = -1;
2005 0 : goto EXIT;
2006 : }
2007 :
2008 : /* This function is called by TMC just after fork, so it is good
2009 : * place to initialize scripter internal structures so that they
2010 : * can be independent. */
2011 :
2012 : /* 1) Initialize Parser */
2013 39 : path = NEW2 (char, strlen (cfg_file) + 1);
2014 39 : STRCPY (path, cfg_file, strlen (cfg_file) + 1);
2015 39 : c = strrchr (path, '/');
2016 39 : if (c == NULL) {
2017 0 : cfgdefault = tx_create(getenv("HOME"));
2018 0 : tx_c_append(cfgdefault,"/.min");
2019 0 : c = tx_share_buf(cfgdefault);
2020 0 : dir = c;
2021 0 : file=path;
2022 : }
2023 : else {
2024 39 : *c = '\0';
2025 39 : c++;
2026 39 : dir=path;
2027 39 : file=c;
2028 : }
2029 :
2030 39 : sp = mp_create (dir, file, ENoComments);
2031 39 : if (sp == INITPTR) {
2032 0 : SCRIPTER_RTERR_ARG("Min Parser failed to create", c);
2033 0 : MIN_ERROR ("Min Parser failed to initialize, params: [%s][%s]",
2034 : path, c);
2035 0 : retval = -1;
2036 0 : goto EXIT;
2037 : }
2038 :
2039 39 : msp = mp_section (sp, "[Test]", "[Endtest]", id);
2040 39 : if (msp == INITPTR) {
2041 0 : SCRIPTER_RTERR("Min Parser failed to create");
2042 0 : MIN_ERROR ("Min Section Parser failed to initialize,"
2043 : " params: [%s][%s]",path, c);
2044 0 : retval = -1;
2045 0 : goto EXIT;
2046 : }
2047 :
2048 : /* 2) Create Lego Snake */
2049 39 : mli_create (msp);
2050 :
2051 : /* 3) Initialize scripter and events stuff and shm */
2052 39 : scripter_mod.tp_details = dl_list_create ();
2053 39 : if (scripter_mod.tp_details == INITPTR) {
2054 0 : retval = -1;
2055 0 : SCRIPTER_RTERR("list creation failed");
2056 0 : goto EXIT;
2057 : }
2058 :
2059 39 : scripter_mod.req_events = dl_list_create ();
2060 39 : scripter_mod.mqid = mq_open_queue ('a');
2061 39 : scripter_mod.script_finished = 0;
2062 39 : scripter_mod.tclass_exec = 0;
2063 39 : scripter_mod.extif_pending = ESFalse;
2064 39 : scripter_mod.extif_remote = 0;
2065 39 : scripter_mod.testcomplete = INITPTR;
2066 39 : scripter_mod.canceliferror = ESFalse;
2067 39 : scripter_mod.error_occured = ESFalse;
2068 39 : scripter_mod.sleep = 0;
2069 39 : scripter_mod.expected_var = INITPTR;
2070 39 : scripter_mod.shm_id = shmget (getpid(), 4096,
2071 : IPC_CREAT | 0660);
2072 :
2073 39 : if (scripter_mod.shm_id < 0) {
2074 0 : MIN_ERROR ("Failed to create shared mem segment: %s",
2075 : strerror (errno));
2076 0 : goto EXIT;
2077 : }
2078 39 : MIN_DEBUG ("shmid = %d", scripter_mod.shm_id);
2079 : /* 4) Initialize scripter (the callbacks) */
2080 39 : scripter_init (&scripter_mod.min_scripter_if);
2081 :
2082 : /* 5) Set test result to default (Not Complete) */
2083 39 : scripter_mod.script_tcr.result_ = TP_NC;
2084 39 : memset (scripter_mod.script_tcr.desc_, 0x0, MaxTestResultDescription);
2085 :
2086 : /* 6) Set SIGCHLD and SIGALRM signal handlers */
2087 : /* signal (SIGCHLD, scripter_sigchld_handler); */
2088 39 : signal (SIGCHLD, SIG_IGN);
2089 : /* 7) The uEngine main loop */
2090 2823 : while (!scripter_mod.script_finished || _pending_tests ()) {
2091 :
2092 : /* Check if any messages to us. */
2093 2760 : msg_pending = mq_peek_message (scripter_mod.mqid, pid);
2094 :
2095 : /* If message is waiting then read it and handle. */
2096 2760 : if (msg_pending || scripter_mod.script_finished) {
2097 :
2098 61 : uengine_read_message (scripter_mod.mqid,
2099 : &input_buffer);
2100 61 : uengine_handle_message (scripter_mod.mqid,
2101 : &input_buffer);
2102 : }
2103 :
2104 : /* Execute line of a script. */
2105 2760 : if (_execute_script ()) {
2106 359 : interpreter_next ();
2107 : } else {
2108 : /*sleep to avoid eating up too much cpu time
2109 : smaller usleep times are known to cause
2110 : problems in some hardwares*/
2111 2401 : usleep(10000);
2112 : }
2113 :
2114 : }
2115 :
2116 : /* 8) Set test case result */
2117 24 : if (!scripter_mod.error_occured)
2118 24 : scripter_final_verdict (scripter_mod.tp_details,
2119 : &scripter_mod.script_tcr);
2120 24 : EXIT:
2121 : /* set test case result, default is passed. */
2122 24 : *result = scripter_mod.script_tcr;
2123 :
2124 : /* Do some cleanup */
2125 :
2126 24 : if (scripter_mod.expected_var != INITPTR) {
2127 1 : DELETE (scripter_mod.expected_var);
2128 : }
2129 :
2130 24 : it = dl_list_tail (defines);
2131 48 : while (it != DLListNULLIterator) {
2132 0 : free (dl_list_data (it));
2133 0 : prev_it = dl_list_prev (it);
2134 0 : dl_list_remove_it (it);
2135 0 : it = prev_it;
2136 : }
2137 :
2138 24 : it = dl_list_tail (variables);
2139 195 : while (it != DLListNULLIterator) {
2140 147 : var = dl_list_data (it);
2141 147 : DELETE (var->name_);
2142 147 : if (var->value_ != INITPTR)
2143 147 : DELETE (var->value_);
2144 147 : DELETE (var);
2145 147 : prev_it = dl_list_prev (it);
2146 147 : dl_list_remove_it (it);
2147 147 : it = prev_it;
2148 : }
2149 :
2150 24 : mli_destroy ();
2151 :
2152 24 : it = dl_list_tail (scripter_mod.tp_details);
2153 63 : while (it != DLListNULLIterator) {
2154 15 : stpd = dl_list_data (it);
2155 15 : dl_list_foreach (dl_list_head (stpd->tcr_list_),
2156 : dl_list_tail (stpd->tcr_list_), free);
2157 15 : dl_list_free (&stpd->tcr_list_);
2158 15 : DELETE (stpd);
2159 15 : prev_it = dl_list_prev (it);
2160 15 : dl_list_remove_it (it);
2161 15 : it = prev_it;
2162 : }
2163 :
2164 24 : if (sp != INITPTR) {
2165 24 : mp_destroy (&sp);
2166 : }
2167 24 : if (msp != INITPTR) {
2168 24 : mmp_destroy (&msp);
2169 : }
2170 24 : DELETE (path);
2171 :
2172 24 : if (scripter_mod.shm_id > 0)
2173 24 : sm_destroy (scripter_mod.shm_id);
2174 :
2175 24 : return retval;
2176 : }
2177 :
2178 : /* ------------------------------------------------------------------------- */
2179 : int tm_get_test_cases (const char *cfg_file, DLList ** cases)
2180 63 : {
2181 63 : int retval = ENOERR;
2182 63 : MinParser *sp = INITPTR;
2183 63 : MinSectionParser *msp = INITPTR;
2184 63 : char *cfg_file_backup = INITPTR;
2185 63 : char *c = INITPTR;
2186 63 : unsigned int section_number = 1;
2187 63 : char *test_case_name = INITPTR, *tmp;
2188 63 : Text *homemindir = INITPTR;
2189 63 : char *dir = INITPTR;
2190 63 : char *file = INITPTR;
2191 :
2192 : /* 0) First call initializes global list of libraries and ptrs
2193 : * to api functions from them. Deallocating of this list is
2194 : * unfortunatelly quite problematical.
2195 : */
2196 63 : if (tp_handlers == INITPTR) {
2197 63 : tp_handlers = dl_list_create ();
2198 : }
2199 :
2200 :
2201 63 : if (defines == INITPTR) {
2202 63 : defines = dl_list_create ();
2203 : }
2204 :
2205 :
2206 63 : if (variables == INITPTR) {
2207 63 : variables = dl_list_create ();
2208 63 : declare_internal_var ("FAIL_COUNT");
2209 63 : declare_internal_var ("CRASH_COUNT");
2210 63 : declare_internal_var ("TOUT_COUNT");
2211 63 : declare_internal_var ("ABORT_COUNT");
2212 63 : declare_internal_var ("ERROR_COUNT");
2213 63 : declare_internal_var ("TOTAL_COUNT");
2214 : }
2215 :
2216 :
2217 : /* 1) Perform POST */
2218 63 : if (cfg_file == INITPTR) {
2219 0 : retval = -1;
2220 0 : errno = EINVAL;
2221 0 : SCRIPTER_RTERR ("Configuration file missing");
2222 0 : goto EXIT;
2223 : }
2224 63 : if (*cases == INITPTR) {
2225 0 : retval = -1;
2226 0 : errno = EINVAL;
2227 0 : SCRIPTER_RTERR ("Cases list missing");
2228 0 : goto EXIT;
2229 : }
2230 :
2231 : /* 2) Initialize the scripter plugin */
2232 63 : scripter_init (&scripter_mod.min_scripter_if);
2233 :
2234 : /* 3) Validate script syntax.
2235 : * This is connected to returning test cases. If test case is
2236 : * valid then its title is added to the *cases list, if not then
2237 : * title is not added and warning is logged */
2238 :
2239 63 : cfg_file_backup = NEW2 (char, strlen (cfg_file) + 1);
2240 63 : STRCPY (cfg_file_backup, cfg_file, strlen (cfg_file) + 1);
2241 :
2242 63 : c = strrchr (cfg_file_backup, '/');
2243 63 : if (c == NULL) {
2244 0 : c = getenv("HOME");
2245 0 : if (c) {
2246 0 : homemindir = tx_create("");
2247 0 : tx_c_append (homemindir,c);
2248 0 : tx_c_append (homemindir,"/.min");
2249 0 : dir = tx_share_buf(homemindir);
2250 0 : file = cfg_file_backup;
2251 0 : } else c = cfg_file_backup;
2252 : } else {
2253 63 : *c = '\0';
2254 63 : c++;
2255 63 : dir = cfg_file_backup;
2256 63 : file = c;
2257 : }
2258 :
2259 63 : sp = mp_create (dir, file, ENoComments);
2260 :
2261 63 : if (sp == INITPTR) {
2262 0 : tmp = NEW2 (char, strlen (cfg_file_backup) + strlen (c) +
2263 : strlen ("MinParser not created with "
2264 : "params:[%s][%s]") +1 );
2265 0 : sprintf (tmp, "MinParser not created with params:"
2266 : "[%s][%s]", cfg_file_backup, c);
2267 0 : SCRIPTER_RTERR_ARG(tmp, strerror (errno));
2268 0 : DELETE (tmp);
2269 0 : MIN_ERROR ("MinParser failed to be created, params:"
2270 : "[%s][%s]: errno: %d",
2271 : cfg_file_backup, c, errno);
2272 0 : retval = -1;
2273 0 : goto EXIT;
2274 : }
2275 :
2276 :
2277 : /* Lets validate DEFINE section if present */
2278 63 : msp = mp_section (sp, "[Define]", "[Enddefine]", 1);
2279 63 : if (msp != INITPTR) {
2280 0 : if (validate_define (msp) == ESFalse) {
2281 : /* define section is not correct --> no sense
2282 : to process further */
2283 0 : mmp_destroy (&msp);
2284 0 : mp_destroy (&sp);
2285 0 : DELETE (cfg_file_backup);
2286 0 : dl_list_free (&tp_handlers);
2287 0 : goto EXIT;
2288 : }
2289 : }
2290 :
2291 63 : mmp_destroy (&msp);
2292 :
2293 : /* Let's validate TEST CASES */
2294 63 : msp = mp_section (sp, "[Test]", "[Endtest]", section_number);
2295 1088 : while (msp != INITPTR) {
2296 :
2297 : /* validate syntax. In return we get TC name or INITPTR */
2298 962 : test_case_name = validate_test_case (msp);
2299 962 : if (test_case_name == NULL)
2300 76 : test_case_name = INITPTR;
2301 :
2302 : /* add TC to list */
2303 962 : if (test_case_name != INITPTR) {
2304 886 : ENTRY2 (*cases /* List of cases */
2305 : , test_case_name /* TC name */
2306 : , section_number); /* TC id */
2307 886 : DELETE (test_case_name);
2308 : } else {
2309 76 : MIN_WARN ("Test case is not valid! [%d]",
2310 : section_number);
2311 :
2312 : }
2313 :
2314 : /* fetch next TC from file */
2315 962 : section_number++;
2316 962 : mmp_destroy (&msp);
2317 962 : msp = mp_section (sp, "[Test]", "[Endtest]", section_number);
2318 : }
2319 :
2320 63 : tx_destroy(&homemindir);
2321 63 : mp_destroy (&sp);
2322 63 : DELETE (cfg_file_backup);
2323 63 : MIN_INFO ("Number of cases %d", dl_list_size (*cases));
2324 63 : EXIT:
2325 :
2326 63 : return retval;
2327 : }
2328 :
2329 : /* ------------------------------------------------------------------------- */
2330 : int testclass_print (MinItemParser * mip)
2331 41 : {
2332 41 : int retval = ENOERR;
2333 41 : char *token = INITPTR;
2334 : Text *txt;
2335 :
2336 41 : txt = tx_create (INITPTR);
2337 :
2338 217 : while (mip_get_next_string (mip, &token) == ENOERR) {
2339 135 : tx_c_append (txt, var_value (token));
2340 135 : tx_c_append (txt, " ");
2341 : }
2342 41 : DELETE (token);
2343 41 : tx_c_prepend (txt, "script: ");
2344 41 : tm_printf (5, "script", tx_share_buf (txt));
2345 :
2346 41 : tx_destroy (&txt);
2347 41 : return retval;
2348 : }
2349 :
2350 : /* ------------------------------------------------------------------------- */
2351 : int testclass_allownextresult (int nextresult, MinItemParser * mip)
2352 2 : {
2353 2 : int retval = ENOERR;
2354 2 : int *result = INITPTR;
2355 :
2356 2 : if (allowedresults == INITPTR) {
2357 1 : allowedresults = dl_list_create ();
2358 : }
2359 :
2360 : /* Add one mandatory result and continue if there are more of them */
2361 : do {
2362 2 : result = NEW (int);
2363 2 : *result = nextresult;
2364 2 : dl_list_add (allowedresults, (void *)result);
2365 2 : retval = mip_get_next_int (mip, &nextresult);
2366 2 : } while (retval == ENOERR);
2367 :
2368 : /* At this point function return no error */
2369 2 : retval = ENOERR;
2370 2 : return retval;
2371 : }
2372 :
2373 : /* ------------------------------------------------------------------------- */
2374 : int testclass_allowerrorcodes (int nexterrorcode, MinItemParser * mip)
2375 0 : {
2376 0 : int retval = ENOERR;
2377 0 : int *error = INITPTR;
2378 :
2379 0 : if (allowederrors == INITPTR) {
2380 0 : allowederrors = dl_list_create ();
2381 : }
2382 :
2383 : /* Add one mandatory error and continue if there are more of them */
2384 : do {
2385 0 : error = NEW (int);
2386 0 : *error = nexterrorcode;
2387 0 : dl_list_add (allowederrors, (void *)error);
2388 0 : retval = mip_get_next_int (mip, &nexterrorcode);
2389 0 : } while (retval == ENOERR);
2390 :
2391 : /* At this point function return no error */
2392 0 : retval = ENOERR;
2393 0 : return retval;
2394 : }
2395 :
2396 : /* ------------------------------------------------------------------------- */
2397 : int test_complete (const char *testid)
2398 0 : {
2399 0 : int retval = ENOERR;
2400 0 : DLListIterator it = DLListNULLIterator;
2401 : ScriptedTestProcessDetails *stpd;
2402 0 : int tc_not_ended=0;
2403 :
2404 0 : if (testid == INITPTR) {
2405 0 : retval = -1;
2406 0 : errno = EINVAL;
2407 0 : SCRIPTER_RTERR ("test id missing");
2408 0 : goto EXIT;
2409 : }
2410 :
2411 : /* Check if test of given testid exists */
2412 0 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
2413 : , dl_list_tail (scripter_mod.tp_details)
2414 : , _findid, (void *)testid);
2415 0 : if (it == DLListNULLIterator) {
2416 0 : SCRIPTER_RTERR_ARG ("No test of specified testid", testid);
2417 0 : MIN_WARN ("No test of specified testid [%s]", testid);
2418 0 : retval = -1;
2419 0 : goto EXIT;
2420 : }
2421 :
2422 : /* Check if test with given testid has already completed */
2423 0 : while (it != DLListNULLIterator) {
2424 0 : stpd = dl_list_data (it);
2425 0 : if (stpd->status_ != TP_ENDED) {
2426 0 : tc_not_ended = tc_not_ended + 1;
2427 : }
2428 0 : it = dl_list_next (it);
2429 0 : if (it == DLListNULLIterator)
2430 0 : break;
2431 0 : it = dl_list_find (it, dl_list_tail (scripter_mod.tp_details),
2432 : _findid, (void *)testid);
2433 : }
2434 0 : if(tc_not_ended==0){
2435 0 : MIN_WARN ("All tests with testid= %s already completed", testid);
2436 0 : goto EXIT;
2437 : }
2438 : /* Set 'wait for complete' flag */
2439 0 : scripter_mod.testcomplete = NEW2 (char, strlen (testid) + 1);
2440 0 : STRCPY (scripter_mod.testcomplete, testid, strlen (testid) + 1);
2441 :
2442 0 : EXIT:
2443 0 : return retval;
2444 : }
2445 :
2446 : /* ------------------------------------------------------------------------- */
2447 : int test_pause (char *testid, MinItemParser * mip)
2448 2 : {
2449 2 : int retval = ENOERR;
2450 : union sigval val;
2451 : int time;
2452 2 : DLListIterator it = INITPTR;
2453 2 : ScriptedTestProcessDetails *stpd = INITPTR;
2454 : char tmp[12];
2455 :
2456 2 : if (testid == INITPTR || strlen (testid) == 0) {
2457 0 : errno = EINVAL;
2458 0 : retval = -1;
2459 0 : SCRIPTER_RTERR("test id missing");
2460 0 : goto EXIT;
2461 : }
2462 :
2463 2 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
2464 : , dl_list_tail (scripter_mod.tp_details)
2465 : , _findid, (void *)testid);
2466 :
2467 2 : if (it == DLListNULLIterator) {
2468 0 : errno = ENODATA;
2469 0 : retval = -1;
2470 0 : SCRIPTER_RTERR_ARG ("Testid not found", testid);
2471 0 : MIN_ERROR ("Testid not found on list");
2472 0 : goto EXIT;
2473 : }
2474 :
2475 2 : val.sival_int = 0;
2476 2 : if (mip_get_next_tagged_int (mip, "time", &time) == ENOERR)
2477 1 : val.sival_int = time;
2478 :
2479 2 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
2480 :
2481 2 : if (stpd->status_ == TP_RUNNING) {
2482 2 : sched_yield ();
2483 2 : retval = sigqueue (stpd->pid_, SIGTSTP, val);
2484 2 : if (retval == -1) {
2485 0 : sprintf (tmp, "%u", stpd->pid_);
2486 0 : SCRIPTER_RTERR_ARG ("Cannot pause", tmp);
2487 0 : MIN_WARN ("Cannot pause %d", stpd->pid_);
2488 : }
2489 : else {
2490 2 : stpd->status_ = TP_PAUSED;
2491 2 : MIN_INFO ("paused %d", stpd->pid_);
2492 : }
2493 : }
2494 :
2495 2 : EXIT:
2496 2 : return retval;
2497 : }
2498 :
2499 : /* ------------------------------------------------------------------------- */
2500 : int test_resume (char *testid)
2501 1 : {
2502 1 : int retval = ENOERR;
2503 1 : DLListIterator it = INITPTR;;
2504 1 : ScriptedTestProcessDetails *stpd = INITPTR;
2505 : char tmp [12];
2506 :
2507 1 : if (testid == INITPTR || strlen (testid) == 0) {
2508 0 : errno = EINVAL;
2509 0 : retval = -1;
2510 0 : SCRIPTER_RTERR ("Test id missing");
2511 0 : goto EXIT;
2512 : }
2513 :
2514 1 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
2515 : , dl_list_tail (scripter_mod.tp_details)
2516 : , _findid, (void *)testid);
2517 :
2518 1 : if (it == DLListNULLIterator) {
2519 0 : errno = ENODATA;
2520 0 : retval = -1;
2521 0 : SCRIPTER_RTERR_ARG ("Testid not found", testid);
2522 0 : MIN_ERROR ("Testid not found on list");
2523 0 : goto EXIT;
2524 : }
2525 :
2526 1 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
2527 :
2528 1 : if (stpd->status_ == TP_PAUSED) {
2529 1 : retval = kill (stpd->pid_, SIGCONT);
2530 1 : if (retval == -1) {
2531 0 : sprintf (tmp, "%u", stpd->pid_);
2532 0 : SCRIPTER_RTERR_ARG ("Cannot resume", tmp);
2533 0 : MIN_WARN ("Cannot resume %d", stpd->pid_);
2534 : }
2535 : else {
2536 1 : stpd->status_ = TP_RUNNING;
2537 1 : MIN_INFO ("Resumed %d", stpd->pid_);
2538 : }
2539 : }
2540 :
2541 1 : EXIT:
2542 1 : return retval;
2543 : }
2544 :
2545 : /* ------------------------------------------------------------------------- */
2546 : int test_cancel (char *testid)
2547 1 : {
2548 1 : int retval = ENOERR;
2549 1 : DLListIterator it = INITPTR;;
2550 1 : ScriptedTestProcessDetails *stpd = INITPTR;
2551 : char tmp [12];
2552 :
2553 1 : if (testid == INITPTR || strlen (testid) == 0) {
2554 0 : errno = EINVAL;
2555 0 : retval = -1;
2556 0 : SCRIPTER_RTERR ("Test id missing");
2557 0 : goto EXIT;
2558 : }
2559 :
2560 1 : it = dl_list_find (dl_list_head (scripter_mod.tp_details)
2561 : , dl_list_tail (scripter_mod.tp_details)
2562 : , _findid, (void *)testid);
2563 :
2564 1 : if (it == DLListNULLIterator) {
2565 0 : errno = ENODATA;
2566 0 : retval = -1;
2567 0 : SCRIPTER_RTERR_ARG ("Testid not found", testid);
2568 0 : MIN_ERROR ("Testid not found on list");
2569 0 : goto EXIT;
2570 : }
2571 :
2572 1 : stpd = (ScriptedTestProcessDetails *) dl_list_data (it);
2573 :
2574 1 : retval = kill (stpd->pid_, SIGKILL);
2575 1 : if (retval == -1) {
2576 0 : sprintf (tmp, "%u", stpd->pid_);
2577 0 : SCRIPTER_RTERR_ARG ("Cannot cancel", tmp);
2578 0 : MIN_WARN ("Cannot cancel %d", stpd->pid_);
2579 : }
2580 : else {
2581 1 : stpd->status_ = TP_ABORTED;
2582 1 : update_variables (TP_NC);
2583 1 : MIN_INFO ("cancelled %d", stpd->pid_);
2584 : }
2585 :
2586 1 : EXIT:
2587 1 : return retval;
2588 : }
2589 :
2590 : /* ------------------------------------------------------------------------- */
2591 : int test_allocate_slave (const char *slave_type, const char *slave_name)
2592 3 : {
2593 3 : int retval = ENOERR;
2594 : MsgBuffer msg;
2595 3 : msg.receiver_ = getppid ();
2596 3 : msg.sender_ = getpid ();
2597 3 : msg.type_ = MSG_EXTIF;
2598 3 : msg.param_ = 0;
2599 3 : msg.extif_msg_type_ = EAllocateSlave;
2600 :
2601 3 : if (slave_type == INITPTR) {
2602 0 : retval = -1;
2603 0 : errno = EINVAL;
2604 0 : SCRIPTER_RTERR ("slave type missing");
2605 0 : goto EXIT;
2606 : }
2607 3 : if (slave_name == INITPTR || strlen (slave_name) == 0) {
2608 0 : retval = -1;
2609 0 : errno = EINVAL;
2610 0 : SCRIPTER_RTERR ("slave name missing");
2611 0 : goto EXIT;
2612 : }
2613 :
2614 3 : STRCPY (msg.desc_, slave_type, MaxDescSize);
2615 3 : STRCPY (msg.message_, slave_name, MaxMsgSize);
2616 3 : mq_send_message (scripter_mod.mqid, &msg);
2617 :
2618 : /* Stop execution till response comes */
2619 3 : scripter_mod.extif_pending = ESTrue;
2620 3 : EXIT:
2621 3 : return retval;
2622 : }
2623 :
2624 : /* ------------------------------------------------------------------------- */
2625 : int test_free_slave (const char *slave_name)
2626 3 : {
2627 3 : int retval = ENOERR;
2628 : MsgBuffer msg;
2629 3 : msg.receiver_ = getppid ();
2630 3 : msg.sender_ = getpid ();
2631 3 : msg.type_ = MSG_EXTIF;
2632 3 : msg.param_ = 0;
2633 3 : msg.extif_msg_type_ = EFreeSlave;
2634 :
2635 3 : if (slave_name == INITPTR || strlen (slave_name) == 0) {
2636 0 : retval = -1;
2637 0 : errno = EINVAL;
2638 0 : SCRIPTER_RTERR ("slave_name missing");
2639 0 : goto EXIT;
2640 : }
2641 :
2642 3 : STRCPY (msg.message_, slave_name, MaxMsgSize);
2643 3 : mq_send_message (scripter_mod.mqid, &msg);
2644 :
2645 : /* Stop execution till response comes */
2646 3 : scripter_mod.extif_pending = ESTrue;
2647 3 : EXIT:
2648 3 : return retval;
2649 : }
2650 :
2651 : /* ------------------------------------------------------------------------- */
2652 : int test_remote_exe (const char *slave_name, MinItemParser * mip)
2653 3 : {
2654 : MsgBuffer msg;
2655 3 : int retval = ENOERR;
2656 3 : int send_extif = 1;
2657 3 : char *kw = INITPTR;
2658 3 : char *token = INITPTR;
2659 3 : char *token2 = INITPTR;
2660 : char *p;
2661 :
2662 3 : if (slave_name == INITPTR || strlen (slave_name) == 0) {
2663 0 : retval = -1;
2664 0 : errno = EINVAL;
2665 0 : SCRIPTER_RTERR ("slave name missing");
2666 0 : goto EXIT;
2667 : }
2668 :
2669 3 : if (mip == INITPTR) {
2670 0 : retval = -1;
2671 0 : errno = EINVAL;
2672 0 : SCRIPTER_RTERR ("item parser argument missing");
2673 0 : goto EXIT;
2674 : }
2675 :
2676 : /* save in case we need to send */
2677 3 : STRCPY (msg.message_, slave_name, MaxMsgSize);
2678 3 : STRCPY (msg.desc_, mip->item_skip_and_mark_pos_, MaxDescSize);
2679 :
2680 3 : mip_get_next_string (mip, &kw);
2681 :
2682 3 : switch (get_keyword (kw)) {
2683 : case EKeywordRequest:
2684 : /*
2685 : ** Create a local "shadow" event for the remote
2686 : */
2687 0 : mip_get_next_string (mip, &token);
2688 0 : mip_get_next_string (mip, &token2);
2689 0 : if (token2 != INITPTR && !strcmp (token2, "state"))
2690 0 : event_request (token, 1);
2691 : else
2692 0 : event_request (token, 0);
2693 0 : break;
2694 : case EKeywordRelease:
2695 0 : mip_get_next_string (mip, &token);
2696 0 : event_release (token);
2697 0 : break;
2698 : case EKeywordWait:
2699 0 : mip_get_next_string (mip, &token);
2700 0 : send_extif = 0;
2701 0 : event_wait (token);
2702 0 : break;
2703 : case EKeywordRun:
2704 : /* Stop execution till response comes */
2705 2 : scripter_mod.extif_pending = ESTrue;
2706 2 : break;
2707 : case EKeywordExpect:
2708 1 : scripter_mod.extif_pending = ESTrue;
2709 1 : mip_get_next_string (mip, &scripter_mod.expected_var);
2710 1 : MIN_DEBUG ("master expecting variable %s",
2711 : scripter_mod.expected_var);
2712 1 : break;
2713 : case EKeywordSendreceive:
2714 0 : mip_get_next_string (mip, &token);
2715 0 : p = strchr (token, '=');
2716 0 : *p = '\0';
2717 0 : p++;
2718 0 : snprintf (msg.desc_, MaxDescSize, "sendreceive %s=%s",
2719 : token, var_value(p));
2720 :
2721 0 : break;
2722 : default:
2723 0 : MIN_WARN ("Unknown keyword [%s]", kw);
2724 : break;
2725 : }
2726 :
2727 3 : if (send_extif) {
2728 3 : msg.receiver_ = getppid ();
2729 3 : msg.sender_ = getpid ();
2730 3 : msg.type_ = MSG_EXTIF;
2731 3 : msg.param_ = 0;
2732 3 : msg.extif_msg_type_ = ERemoteSlave;
2733 3 : mq_send_message (scripter_mod.mqid, &msg);
2734 : }
2735 3 : EXIT:
2736 3 : return retval;
2737 : }
2738 :
2739 : /* ------------------------------------------------------------------------- */
2740 : int test_canceliferror ()
2741 3 : {
2742 3 : scripter_mod.canceliferror = ESTrue;
2743 3 : return ENOERR;
2744 : }
2745 :
2746 : /* ------------------------------------------------------------------------- */
2747 : int testclass_test_timeout (unsigned long interval)
2748 0 : {
2749 0 : unsigned long timeout = 0;
2750 0 : int retval = ENOERR;
2751 :
2752 : /* ualarm fails when timeout greater that 1000^2 useconds, we have to
2753 : * use either alarm or ualarm.
2754 : * alarm for timeouts >= 1 [sec]
2755 : * ualarm for timeouts < 1 [sec]
2756 : */
2757 0 : if (interval > 999) {
2758 0 : timeout = interval / (unsigned long)1000;
2759 0 : retval = alarm (timeout);
2760 0 : signal (SIGALRM, scripter_sigalrm_handler);
2761 : } else {
2762 0 : timeout = interval * (unsigned long)1000;
2763 0 : retval = ualarm (timeout, 0);
2764 0 : signal (SIGALRM, scripter_sigalrm_handler);
2765 : }
2766 :
2767 0 : if (retval == -1) {
2768 0 : SCRIPTER_RTERR_ARG ("Error in setting the timeout",
2769 : strerror (errno));
2770 0 : MIN_ERROR ("Error in setting the timeout: [%s]",
2771 : strerror (errno));
2772 : } else {
2773 0 : MIN_DEBUG ("Starting timeout: [%d] miliseconds", interval);
2774 0 : retval = ENOERR;
2775 : }
2776 0 : return retval;
2777 : }
2778 :
2779 : /* ------------------------------------------------------------------------- */
2780 : int testclass_test_sleep (unsigned long interval)
2781 10 : {
2782 10 : scripter_mod.sleep = interval;
2783 10 : gettimeofday (&scripter_mod.time, NULL);
2784 10 : MIN_DEBUG ("Starting sleep: [%d] miliseconds", interval);
2785 10 : return ENOERR;
2786 : }
2787 :
2788 : /* ------------------------------------------------------------------------- */
2789 : int declare_var (char *name, TSBool initialize, char *val)
2790 383 : {
2791 :
2792 : ScriptVar *var;
2793 :
2794 383 : if ((var = var_find (name)) != INITPTR) {
2795 1 : if (initialize == ESFalse) {
2796 0 : SCRIPTER_RTERR_ARG ("Variable already declared", name);
2797 0 : return -1;
2798 : }
2799 1 : var_assign (name, val);
2800 1 : return ENOERR;
2801 : }
2802 382 : if (var_find (name) != INITPTR) {
2803 0 : MIN_WARN ("variable %s already declared", name);
2804 0 : return -1;
2805 : }
2806 382 : var = NEW (ScriptVar);
2807 382 : var->name_ = name;
2808 382 : var->initialized_ = initialize;
2809 382 : if (initialize)
2810 382 : var->value_ = val;
2811 : else
2812 0 : var->value_ = INITPTR;
2813 382 : dl_list_add (variables, var);
2814 382 : MIN_DEBUG ("name=%s init. val=%s", name, initialize ? val : "none");
2815 382 : return ENOERR;
2816 : }
2817 :
2818 : /* ------------------------------------------------------------------------- */
2819 : LOCAL int declare_internal_var (const char *name)
2820 378 : {
2821 : char *var_name, *var_value;
2822 378 : var_value = NEW2(char, 32);
2823 378 : var_name = NEW2(char, strlen (name) + 1);
2824 :
2825 378 : sprintf (var_name, "%s", name);
2826 378 : sprintf (var_value, "%d", 0);
2827 378 : declare_var (var_name, 1, var_value);
2828 378 : return ENOERR;
2829 : }
2830 :
2831 : /* ------------------------------------------------------------------------- */
2832 : int sendreceive_slave_send (char *variable, char *value)
2833 0 : {
2834 : MsgBuffer msg;
2835 :
2836 0 : MIN_DEBUG ("sendreceive var=%s value=%s", variable, value);
2837 0 : msg.receiver_ = getppid ();
2838 0 : msg.sender_ = getpid ();
2839 0 : msg.type_ = MSG_SNDRCV;
2840 0 : STRCPY (msg.message_, variable, MaxMsgSize);
2841 0 : STRCPY (msg.desc_, var_value (value), MaxDescSize);
2842 0 : mq_send_message (scripter_mod.mqid, &msg);
2843 :
2844 0 : return ENOERR;
2845 : }
2846 :
2847 : /* ------------------------------------------------------------------------- */
2848 : int sendreceive_slave_expect (char *variable)
2849 0 : {
2850 : MsgBuffer msg;
2851 0 : msg.receiver_ = getppid ();
2852 0 : msg.sender_ = getpid ();
2853 0 : msg.type_ = MSG_EXTIF;
2854 0 : msg.extif_msg_type_ = ERemoteSlave;
2855 :
2856 0 : if (strlen (variable) >= MaxDescSize - strlen ("expect ")) {
2857 0 : SCRIPTER_RTERR ("too long variable name for expect!");
2858 0 : MIN_ERROR ("Too long variable name!");
2859 0 : return -1;
2860 : }
2861 :
2862 0 : scripter_mod.expected_var = variable;
2863 0 : scripter_mod.extif_pending = ESTrue;
2864 0 : STRCPY (msg.message_, "master", MaxMsgSize);
2865 0 : sprintf (msg.desc_, "expect %s", variable);
2866 0 : mq_send_message (scripter_mod.mqid, &msg);
2867 :
2868 0 : return ENOERR;
2869 : }
2870 : /* ------------------------------------------------------------------------- */
2871 : int test_interference(MinItemParser* args)
2872 27 : {
2873 27 : char* command = INITPTR;
2874 27 : char* name = INITPTR;
2875 27 : char* typename = INITPTR;
2876 27 : int value = 0;
2877 27 : int idle_time = 0;
2878 27 : int busy_time = 0;
2879 27 : TInterferenceType type = ECpuLoad;
2880 27 : InterfHandle* handle = INITPTR;
2881 : DLListIterator work_inter;
2882 :
2883 27 : mip_get_next_string(args,&name);
2884 27 : mip_get_next_string(args,&command);
2885 :
2886 27 : if (strcmp(command,"start") == 0) {
2887 15 : if (interference_handles == INITPTR)
2888 6 : interference_handles = dl_list_create();
2889 15 : mip_get_next_string(args,&typename);
2890 15 : mip_get_next_int(args,&value);
2891 15 : mip_get_next_int(args,&idle_time);
2892 15 : mip_get_next_int(args,&busy_time);
2893 :
2894 15 : if (strcmp(typename,"cpuload") == 0) type = ECpuLoad;
2895 9 : else if (strcmp(typename,"memload") == 0) type = EMemLoad;
2896 3 : else if (strcmp(typename,"ioload") == 0) type = EIOLoad;
2897 : /*validation was successful so there is no point in
2898 : handling other cases here*/
2899 :
2900 15 : handle = NEW(InterfHandle);
2901 15 : sprintf(handle->name_,"%s",name);
2902 15 : handle->instance_ = ti_start_interference_timed (type,
2903 : idle_time,
2904 : busy_time,
2905 : value);
2906 12 : dl_list_add(interference_handles,(void*)handle);
2907 : }
2908 : /*if validation was successful (and we asume so)
2909 : then command is "stop"*/
2910 : else {
2911 12 : work_inter = dl_list_head(interference_handles);
2912 24 : while (work_inter != DLListNULLIterator){
2913 12 : handle = (InterfHandle*)dl_list_data(work_inter);
2914 12 : if (strcmp(handle->name_,name) == 0) break;
2915 0 : work_inter = dl_list_next(work_inter);
2916 : }
2917 12 : ti_stop_interference(handle->instance_);
2918 12 : dl_list_remove_it(work_inter);
2919 12 : DELETE(handle);
2920 : }
2921 24 : return 0;
2922 : }
2923 :
2924 : /* ------------------------------------------------------------------------- */
2925 :
2926 13 : TSBool eval_if (char *condition) {
2927 13 : int i,isnumber = ESTrue;
2928 : const char *value;
2929 :
2930 13 : MIN_DEBUG ("condition = %s", condition);
2931 :
2932 13 : value = var_value (condition);
2933 36 : for (i = 0; i < strlen (value); i++) {
2934 35 : if (!isxdigit(value[i])) {
2935 12 : isnumber = ESFalse;
2936 12 : break;
2937 : }
2938 : }
2939 13 : if (isnumber == ESTrue && strtol (value, NULL, 16) == 0) {
2940 1 : return ESFalse;
2941 : }
2942 12 : if (isnumber == ESFalse && strcasecmp (value, "false") == 0) {
2943 11 : return ESFalse;
2944 : }
2945 :
2946 1 : return ESTrue;
2947 : }
2948 :
2949 :
2950 :
2951 : /* ------------------------------------------------------------------------- */
2952 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
2953 : /* None */
2954 :
2955 : /* ------------------------------------------------------------------------- */
2956 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
2957 : #ifdef MIN_UNIT_TEST
2958 : #include "min_scripter_if.tests"
2959 : #endif /* MIN_UNIT_TEST */
2960 : /* End of file */
|