1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Sampo Saaristo
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 : * @file min_main.c
21 : * @version 0.1
22 : * @brief This file contains implementation of MIN main.
23 : */
24 :
25 : /* ------------------------------------------------------------------------- */
26 : /* INCLUDE FILES */
27 : #include <getopt.h>
28 :
29 : #include <min_common.h>
30 : #include <cli.h>
31 : #include <consoleui.h>
32 : #include <cli.h>
33 : #include <tec.h>
34 : #include <tec_tcp_handling.h>
35 : #include <data_api.h>
36 : #include <min_engine_api.h>
37 : #include <dllist.h>
38 : #include <tllib.h>
39 :
40 : /* ------------------------------------------------------------------------- */
41 : /* EXTERNAL DATA STRUCTURES */
42 : /* None */
43 :
44 : /* ------------------------------------------------------------------------- */
45 : /* EXTERNAL GLOBAL VARIABLES */
46 : extern char* optarg;
47 : extern eapiIn_t in_str;
48 : extern int min_return_value;
49 :
50 : /* ------------------------------------------------------------------------- */
51 : /* EXTERNAL FUNCTION PROTOTYPES */
52 :
53 : /* ------------------------------------------------------------------------- */
54 : /* GLOBAL VARIABLES */
55 : eapiIn_t *in;
56 : eapiOut_t *out;
57 : int slave_exit;
58 : /* ------------------------------------------------------------------------- */
59 : /* CONSTANTS */
60 : /* None */
61 :
62 : /* ------------------------------------------------------------------------- */
63 : /* MACROS */
64 : /* None */
65 :
66 : /* ------------------------------------------------------------------------- */
67 : /* LOCAL GLOBAL VARIABLES */
68 : eapiOut_t out_str;
69 :
70 :
71 : /* ------------------------------------------------------------------------- */
72 : /* LOCAL CONSTANTS AND MACROS */
73 : /* None */
74 :
75 : /* ------------------------------------------------------------------------- */
76 : /* MODULE DATA STRUCTURES */
77 : /* None */
78 :
79 : /* ------------------------------------------------------------------------- */
80 : /* LOCAL FUNCTION PROTOTYPES */
81 : /** Displays the MIN release tag */
82 : LOCAL void display_version ();
83 : /* ------------------------------------------------------------------------- */
84 : /** Displays short help */
85 : LOCAL void display_help ();
86 : /* ------------------------------------------------------------------------- */
87 : /** Appends the pwd to a relative path
88 : * @param p the path coming from commandline
89 : * @return the absolute path
90 : */
91 : LOCAL char *patch_path (char *p);
92 : /* ------------------------------------------------------------------------- */
93 : /** Adds the modules and configuration files given from commandline
94 : * @param modulelist list of module and filenames
95 : * @return 0 - on success, 1 - on error (e.g. file not found)
96 : */
97 : LOCAL int add_command_line_modules (DLList * modulelist);
98 : /* ------------------------------------------------------------------------- */
99 : /** Adds the IP slaves given from commandline through eapi to slave pool
100 : * @param slavelist list of hostnames or ip addresses
101 : * @return 0 - on success, 1 - on error
102 : */
103 : LOCAL int add_ip_slaves (DLList * slavelist);
104 :
105 : /* ------------------------------------------------------------------------- */
106 : /* FORWARD DECLARATIONS */
107 : /* None */
108 :
109 : /* ==================== LOCAL FUNCTIONS ==================================== */
110 : /* ------------------------------------------------------------------------- */
111 : LOCAL void display_license ()
112 9 : {
113 9 : printf ("MIN Test Framework, © Nokia 2008, All rights reserved,\n"
114 : "licensed under the Gnu General Public License version 2,\n"
115 : "Contact: Antti Heimola, DG.MIN-Support@nokia.com\n\n");
116 :
117 9 : }
118 :
119 : LOCAL void display_version ()
120 2 : {
121 :
122 2 : printf ("MIN Test Framework release %s\n", MIN_VERSION_STR);
123 2 : }
124 :
125 : LOCAL void display_help ()
126 3 : {
127 3 : printf ("\nUsage: min [options]\n");
128 3 : printf ("Options:\n");
129 3 : printf (" -h, --help\t\t\tDisplay this information and exits\n");
130 3 : printf (" -v, --version\t\t\t"
131 : "Display version information and exits\n");
132 3 : printf (" -c, --console\t\t\tStart MIN without consoleui\n");
133 3 : printf (" -i, --info test_module\t"
134 : "Print details about test_module and exits\n");
135 3 : printf (" -x, --execute test_module"
136 : "[:configuration_file:... ]\n\t\t\t"
137 : "\tExecute test cases from test_module"
138 : "\n\t\t\t\t(with configuration file(s))\n");
139 3 : printf (" -t, --title title"
140 : "\t\tShow/execute test cases with title\n");
141 3 : printf (" -r, --title-regex regular_experession"
142 : "\n\t\t\t\tShow/execute test cases with title matching"
143 : "\n\t\t\t\tregular_expression\n");
144 3 : printf (" -s, --slave host[:slave_type]"
145 : "\n\t\t\t\tRegister host (with type slave_type) for"
146 : "\n\t\t\t\tmaster/slave testing\n");
147 3 : printf (" -p, --plugin plugin"
148 : "[:plugin2:... ]\n\t\t\t"
149 : "\tLoad input plugin for MIN,\n\t\t\t\tby default cli or cui "
150 : "plugin is loaded\n");
151 3 : printf ("\nReport bugs to:\n");
152 3 : printf ("DG.MIN-Support@nokia.com\n");
153 3 : }
154 :
155 : LOCAL char *patch_path (char *p)
156 6 : {
157 : Text *path, *cwd;
158 : char *retval;
159 :
160 6 : path = tx_create (p);
161 6 : if (*p != '/') { /* relative path have to prepend with pwd */
162 1 : cwd = tx_create (getenv ("PWD"));
163 1 : tx_c_append (cwd, "/");
164 1 : tx_append (cwd, path);
165 1 : retval = tx_get_buf (cwd);
166 1 : tx_destroy (&cwd);
167 : } else
168 5 : retval = tx_get_buf (path);
169 6 : tx_destroy (&path);
170 :
171 6 : return retval;
172 : }
173 :
174 : LOCAL int add_command_line_modules (DLList * modulelist)
175 8 : {
176 :
177 8 : char *path, *command, *p = NULL, *conffname;
178 : DLList *configs_list;
179 : DLListIterator it;
180 : FILE *f;
181 :
182 :
183 21 : for (it = dl_list_head (modulelist); it != DLListNULLIterator;
184 5 : it = dl_list_next (it)) {
185 5 : configs_list = dl_list_create();
186 :
187 5 : command = (char *)dl_list_data (it);
188 11 : while ((p = strrchr (command, ':'))) {
189 1 : *p = '\0';
190 1 : p ++;
191 1 : conffname = patch_path (p);
192 1 : if (!(f = fopen (conffname, "r"))) {
193 0 : fprintf (stderr, "\n*** Could not "
194 : "open %s: %s ***\n",
195 : conffname, strerror (errno));
196 0 : return 1;
197 : }
198 1 : fclose (f);
199 1 : dl_list_add (configs_list, conffname);
200 : }
201 :
202 5 : path = patch_path (command);
203 5 : if (!(f = fopen (path, "r"))) {
204 0 : fprintf (stderr, "\n*** Could not open %s: %s ***\n",
205 : path, strerror (errno));
206 0 : DELETE (path);
207 0 : return 1;
208 : }
209 5 : fclose (f);
210 5 : ec_add_module (path, configs_list, 0, 1);
211 5 : DELETE (path);
212 : }
213 :
214 8 : return 0;
215 : }
216 :
217 : LOCAL int add_ip_slaves (DLList * slavelist)
218 8 : {
219 :
220 8 : char *command, *p = NULL;
221 : DLListIterator it;
222 :
223 :
224 17 : for (it = dl_list_head (slavelist); it != DLListNULLIterator;
225 1 : it = dl_list_next (it)) {
226 1 : command = (char *)dl_list_data (it);
227 1 : if ((p = strrchr (command, ':'))) {
228 1 : *p = '\0';
229 1 : p++;
230 : }
231 1 : if (out_str.register_slave (command, p ? p : "phone")) {
232 0 : fprintf (stderr, "slave \"%s\" registration failed!\n",
233 : command);
234 0 : return 1;
235 : }
236 : }
237 :
238 8 : return 0;
239 : }
240 :
241 :
242 : LOCAL pthread_t load_plugin (const char *plugin_name, void *plugin_conf)
243 8 : {
244 8 : void *pluginhandle = INITPTR;
245 : void (*pl_attach) (eapiIn_t **out_callback,
246 : eapiOut_t *in_callback);
247 : void (*pl_open) (void *arg);
248 : pthread_t plugin_thread;
249 8 : int retval = 0;
250 :
251 : /* Construct plugin name */
252 8 : Text *plugin = tx_create("/usr/lib/min/min_");
253 8 : tx_c_append(plugin,plugin_name);
254 8 : tx_c_append(plugin,".so");
255 :
256 : /* Load plugin and resolve functions from Plugin API */
257 8 : pluginhandle = dlopen(tx_share_buf(plugin),RTLD_NOW);
258 8 : if (!pluginhandle) {
259 0 : printf ("Error opening plugin %s\n", dlerror());
260 0 : exit (-1);
261 : }
262 8 : pl_attach = dlsym (pluginhandle, "pl_attach_plugin");
263 8 : pl_open = dlsym (pluginhandle, "pl_open_plugin");
264 8 : if (!pl_attach || !pl_open) {
265 0 : printf ("Error opening plugin %s\n", dlerror());
266 0 : exit (-1);
267 : }
268 :
269 : /* Initialize Eapi/Attach the plugin */
270 8 : in = &in_str;
271 8 : out = &out_str;
272 8 : pl_attach (&in, out);
273 8 : eapi_init (in, out);
274 8 : pl_attach (&in, out);
275 :
276 : /* Run the plugin */
277 8 : retval = pthread_create (&plugin_thread, NULL, (void *)pl_open,
278 : plugin_conf);
279 :
280 : /* In this fancy way we do display legal and contact information on
281 : * consoleUI. */
282 8 : if (!strcmp (plugin_name, "cui") && in->error_report) {
283 0 : usleep (100000);
284 0 : in->error_report ("Contact: Antti Heimola, "
285 : "DG.MIN-Support@nokia.com");
286 0 : in->error_report ("licensed under the Gnu General "
287 : "Public License version 2,");
288 0 : in->error_report ("MIN Test Framework, (c) Nokia 2008,"
289 : " All rights reserved,");
290 : }
291 :
292 8 : return plugin_thread;
293 : }
294 :
295 : /* ------------------------------------------------------------------------- */
296 : int main (int argc, char *argv[], char *envp[])
297 13 : {
298 : int cont_flag, status, opt_char, oper_mode, exit_flag;
299 : int no_cui_flag, help_flag, version_flag, info_flag;
300 13 : int slave_mode = 0, master_socket = -1;
301 : DLList *modulelist, *slavelist;
302 : DLListIterator work_module_item;
303 : pthread_t plugin_thread[10];
304 13 : void *plugin_opts = NULL;
305 : cli_opts cli_opts;
306 : void *tmp;
307 13 : char *c2 = INITPTR;
308 13 : char *c3 = INITPTR;
309 13 : unsigned int num_of_plugins = 0;
310 13 : Text *plugin = tx_create("cui");
311 13 : memset (&cli_opts, 0x0, sizeof (cli_opts));
312 :
313 : struct option min_options[] =
314 : {
315 : {"help", no_argument, &help_flag, 1},
316 : {"version", no_argument, &version_flag, 1},
317 : {"console", no_argument, &no_cui_flag, 1},
318 : {"info", required_argument, NULL, 'i'},
319 : {"execute", required_argument, NULL, 'x'},
320 : {"slave", required_argument, NULL, 's'},
321 : {"plugin", required_argument, NULL,'p'},
322 : {"title", required_argument, NULL, 't'},
323 : {"title-regex", required_argument, NULL, 'r'},
324 : {"masterfd", required_argument, NULL,'m'}
325 13 : };
326 :
327 13 : modulelist = dl_list_create();
328 13 : slavelist = dl_list_create();
329 13 : work_module_item = DLListNULLIterator;
330 13 : oper_mode = no_cui_flag = help_flag = version_flag = cont_flag = 0;
331 13 : info_flag = exit_flag = 0;
332 :
333 : /* Detect commandline arguments */
334 : while (1) {
335 : /* getopt_long stores the option index here. */
336 39 : int option_index = 0;
337 :
338 39 : opt_char = getopt_long (argc, argv, "hvci:x:s:p:t:r:m:",
339 : min_options, &option_index);
340 :
341 : /* Detect the end of the options. */
342 39 : if (opt_char == -1)
343 13 : break;
344 :
345 26 : switch (opt_char)
346 : {
347 : case 0:
348 6 : break;
349 :
350 : case 'c':
351 5 : no_cui_flag = 1;
352 5 : break;
353 :
354 : case 'v':
355 1 : version_flag = 1;
356 1 : break;
357 :
358 : case 'h':
359 1 : help_flag = 1;
360 1 : break;
361 :
362 : case 'x':
363 5 : oper_mode = 1;
364 5 : dl_list_add (modulelist, optarg);
365 5 : break;
366 :
367 : case '?':
368 2 : help_flag = 1;
369 2 : break;
370 :
371 : case 'i':
372 0 : oper_mode = 1;
373 0 : dl_list_add (modulelist, optarg);
374 0 : no_cui_flag = 1;
375 0 : cli_opts.display_info_ = 1;
376 0 : break;
377 :
378 : case 'p':
379 0 : tx_c_copy (plugin,optarg);
380 0 : break;
381 :
382 : case 's':
383 2 : dl_list_add (slavelist, optarg);
384 2 : break;
385 :
386 : case 'm':
387 0 : slave_mode = 1;
388 0 : no_cui_flag = 1;
389 0 : oper_mode = 0;
390 0 : master_socket = atoi (optarg);
391 0 : break;
392 :
393 : case 't':
394 3 : ec_add_title_filter (optarg, 0);
395 3 : break;
396 :
397 : case 'r':
398 1 : ec_add_title_filter (optarg, 1);
399 1 : break;
400 : default:
401 0 : abort ();
402 : }
403 26 : }
404 :
405 : /* Handle options. */
406 13 : if (no_cui_flag) {
407 9 : display_license();
408 9 : plugin_opts = (void *)&cli_opts;
409 9 : tx_c_copy (plugin, "cli");
410 : }
411 :
412 13 : if (optind < argc) {
413 0 : printf ("unknown options: ");
414 0 : while (optind < argc)
415 0 : printf ("\t%s", argv[optind++]);
416 0 : display_help();
417 0 : exit (0);
418 : }
419 :
420 13 : if (version_flag && help_flag) {
421 0 : display_version();
422 0 : display_help();
423 0 : exit (0);
424 : }
425 13 : if (version_flag) {
426 2 : display_version();
427 2 : exit (0);
428 : }
429 :
430 11 : if (help_flag) {
431 3 : display_help();
432 3 : exit (0);
433 : }
434 :
435 8 : if (exit_flag) {
436 0 : exit (0);
437 : }
438 :
439 : /* Perform application start-up */
440 8 : ec_min_init (envp, oper_mode);
441 :
442 8 : if (slave_mode) {
443 0 : in = &in_str;
444 0 : out = &out_str;
445 0 : eapi_init (in, out);
446 0 : ec_configure();
447 0 : new_tcp_master (master_socket);
448 0 : while (slave_exit == 0)
449 0 : usleep (500000);
450 0 : ec_cleanup();
451 0 : return 0;
452 :
453 : }
454 : /**
455 : * Load plugin and go
456 : */
457 8 : c2 = tx_get_buf(plugin);
458 : do {
459 8 : c3 = strchr (c2,':');
460 8 : if (c3!=NULL) (*c3) = '\0';
461 8 : plugin_thread[0] = load_plugin(c2, plugin_opts);
462 8 : num_of_plugins++;
463 : /* Multiple plugins not supported yet by engine.
464 : * FIXME: remove in future following line. */
465 : break;
466 : if (c3==NULL) break;
467 : c2 = c3+1;
468 : } while (c3!=NULL);
469 8 : tx_destroy (&plugin);
470 8 : if (add_command_line_modules (modulelist) ||
471 : add_ip_slaves (slavelist)) {
472 0 : exit (-1);
473 : }
474 :
475 8 : pthread_join (plugin_thread[0], &tmp);
476 :
477 :
478 8 : dl_list_free (&modulelist);
479 8 : dl_list_free (&slavelist);
480 8 : ec_cleanup ();
481 :
482 8 : return min_return_value;
483 : }
484 :
485 : /* ------------------------------------------------------------------------- */
486 : /* ======================== FUNCTIONS ====================================== */
487 : /* None */
488 :
489 : /* ------------------------------------------------------------------------- */
490 :
491 : /* ------------------------------------------------------------------------- */
492 :
493 : /* ------------------------------------------------------------------------- */
494 :
495 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
496 : /* None */
497 :
498 : /* ------------------------------------------------------------------------- */
499 : /* End of file */
|