Initial commit.
[qa-tools:testrunner-lite.git] / tests / unit / ut_features.c
1 /*
2  * This file is part of testrunner-lite
3  *
4  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5  *
6  * Contact: Sami Lahtinen <ext-sami.t.lahtinen@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 /* ------------------------------------------------------------------------- */
25 /* INCLUDE FILES */
26 #include <check.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <sys/types.h> 
33 #include <sys/socket.h>
34 #include <sys/wait.h>
35 #include <netinet/in.h>
36
37 #include "testrunnerlitetestscommon.h"
38 #include "executor.h"
39 #include "hwinfo.h"
40 #include "log.h"
41
42 /* ------------------------------------------------------------------------- */
43 /* EXTERNAL DATA STRUCTURES */
44 /* None */
45
46 /* ------------------------------------------------------------------------- */
47 /* EXTERNAL GLOBAL VARIABLES */
48 /* None */
49
50 /* ------------------------------------------------------------------------- */
51 /* EXTERNAL FUNCTION PROTOTYPES */
52 /* None */
53
54 /* ------------------------------------------------------------------------- */
55 /* GLOBAL VARIABLES */
56 /* None */
57
58 /* ------------------------------------------------------------------------- */
59 /* CONSTANTS */
60 /* None */
61
62 /* ------------------------------------------------------------------------- */
63 /* MACROS */
64 /* None */
65
66 /* ------------------------------------------------------------------------- */
67 /* LOCAL GLOBAL VARIABLES */
68 /* None */
69
70 /* ------------------------------------------------------------------------- */
71 /* LOCAL CONSTANTS AND MACROS */
72 /* None */
73
74 /* ------------------------------------------------------------------------- */
75 /* MODULE DATA STRUCTURES */
76 /* None */
77
78 /* ------------------------------------------------------------------------- */
79 /* LOCAL FUNCTION PROTOTYPES */
80 /* ------------------------------------------------------------------------- */
81 /* None */
82
83 /* ------------------------------------------------------------------------- */
84 /* FORWARD DECLARATIONS */
85 /* None */
86
87 /* ------------------------------------------------------------------------- */
88 /* ==================== LOCAL FUNCTIONS ==================================== */
89 /* ------------------------------------------------------------------------- */
90 START_TEST (test_ctrl_char_strip)
91     exec_data edata;
92     char cmd[1024];
93     const char test_str[] = {'t',0x02,'e','s','t','f',0x06,0x07,0x08,0x09,
94                              'o',0x0B,'o',0x0C,0x0E,0x0F,0x10,0x11,0x12,
95                              0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
96                              0x1C,0x1D,0x1E,0x1F,0x7F,'b','a','r'};
97
98      const char valid_str[] = {'t',' ','e','s','t','f',' ',' ',' ',' ',
99                                'o',' ','o',' ',' ',' ',' ',' ',' ',
100                                ' ',' ',' ',' ',' ',' ',' ',' ',' ',
101                                ' ',' ',' ',' ',' ','b','a','r', '\0'};
102
103     
104     testrunner_lite_options opts;
105
106     memset (&opts, 0x0, sizeof (opts));
107     executor_init (&opts);
108
109     init_exec_data(&edata);
110     edata.soft_timeout = 0;
111     edata.hard_timeout = 0;
112     sprintf (cmd, "echo -e %s", test_str); 
113     fail_if (execute(cmd, &edata));
114     fail_if (strlen ((char *)edata.stdout_data.buffer) == 0);
115     fail_unless (strlen ((char *)edata.stderr_data.buffer) == 0);
116     fail_if (strncmp ((char *)edata.stdout_data.buffer, valid_str, 
117                       strlen (valid_str)),
118              "FAIL: stdout %s != %s", edata.stdout_data.buffer, valid_str);
119
120 END_TEST
121
122 START_TEST (test_logging)
123
124     char *stdout_tmp = "/tmp/testrunner-lite-stdout.log";
125     char cmd[1024];
126     char message[LOG_MSG_MAX_SIZE + 1];
127     int ret;
128     FILE *fp;
129     testrunner_lite_options opts;
130     memset (&opts, 0x0, sizeof (testrunner_lite_options)); 
131     memset (message, 'a', LOG_MSG_MAX_SIZE);
132     message [LOG_MSG_MAX_SIZE - 1] = '\0';
133     message [LOG_MSG_MAX_SIZE - 2] = 'b';
134
135     /* Set verbosity to INFO. */
136     opts.log_level = LOG_LEVEL_INFO;
137     log_init (&opts);
138     
139     /* Forward stdout temporarily to a file. */
140     fp = freopen (stdout_tmp, "w", stdout);
141     
142     /* Log INFO, WARNING and ERROR messages. */
143     LOG_MSG (LOG_INFO, "INFO message: %s\n", "This works.");
144     LOG_MSG (LOG_WARNING, "WARNING message: %s\n", "This works.");
145     LOG_MSG (LOG_ERR, "ERROR message: %s\n", "This works.");
146     LOG_MSG (LOG_INFO, message);
147     memset (message, 'b', LOG_MSG_MAX_SIZE + 1);
148     message [LOG_MSG_MAX_SIZE] = '\0';
149     
150     /* Back to terminal. */
151     freopen ("/dev/tty", "w", stdout);
152
153     // And verify messages. */
154     sprintf (cmd, "grep \"[INFO]* INFO message: This works.\" %s", stdout_tmp); 
155     ret = system (cmd);
156     fail_if (ret != 0, cmd);
157     
158     sprintf (cmd, "grep \"[WARNING]* WARNING message: This works.\" %s", 
159              stdout_tmp); 
160     ret = system (cmd);
161     fail_if (ret != 0, cmd);
162     
163     sprintf (cmd, "grep \"[ERROR]* ERROR message: This works.\" %s", stdout_tmp); 
164     ret = system (cmd);
165     fail_if (ret != 0, cmd);
166     
167     sprintf (cmd, "grep aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab %s", stdout_tmp); 
168     ret = system (cmd);
169     fail_if (ret != 0, cmd);
170
171     sprintf (cmd, "grep bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb %s", stdout_tmp); 
172     ret = system (cmd);
173     fail_unless (ret != 0, cmd);
174
175
176     /* Try to log DEBUG message with INFO verbosity (should not succeed.)*/
177     LOG_MSG (LOG_DEBUG, "DEBUG message: %s\n", "This should not work.");
178     freopen ("/dev/tty", "w", stdout);
179     
180     sprintf (cmd, "grep \"[DEBUG]* DEBUG message: This should not work.\" %s", stdout_tmp); 
181     ret = system (cmd);
182     fail_if (ret == 0, cmd);
183     
184     /* Set verbosity to DEBUG. */
185     opts.log_level = LOG_LEVEL_DEBUG;
186     log_init (&opts);
187     
188     /* Forward stdout temporarily to a file. */
189     fp = freopen (stdout_tmp, "w", stdout);
190     
191     /* Log INFO, WARNING and ERROR messages. */
192     LOG_MSG (LOG_INFO, "INFO message: %s\n", "This works.");
193     LOG_MSG (LOG_WARNING, "WARNING message: %s\n", "This works.");
194     LOG_MSG (LOG_ERR, "ERROR message: %s\n", "This works.");
195     LOG_MSG (LOG_DEBUG, "DEBUG message: %s\n", "This works.");
196     
197     /* Back to terminal. */
198     freopen ("/dev/tty", "w", stdout);
199
200     // And verify messages. */
201     sprintf (cmd, "grep \"[INFO]* INFO message: This works.\" %s", stdout_tmp); 
202     ret = system (cmd);
203     fail_if (ret != 0, cmd);
204     
205     sprintf (cmd, "grep \"[WARNING]* WARNING message: This works.\" %s", stdout_tmp); 
206     ret = system (cmd);
207     fail_if (ret != 0, cmd);
208     
209     sprintf (cmd, "grep \"[ERROR]* ERROR message: This works.\" %s", stdout_tmp); 
210     ret = system (cmd);
211     fail_if (ret != 0, cmd);
212     
213     sprintf (cmd, "grep \"[DEBUG]* DEBUG message: This works.\" %s", stdout_tmp); 
214     ret = system (cmd);
215     fail_if (ret != 0, cmd);
216     
217     /* Set verbosity to SILENT. */
218     opts.log_level = LOG_LEVEL_SILENT;
219     log_init (&opts);
220     
221     /* Forward stdout temporarily to a file. */
222     fp = freopen (stdout_tmp, "w", stdout);
223     
224     LOG_MSG (LOG_INFO, "INFO message: %s\n", "Silent mode.");
225     
226     /* Back to terminal. */
227     freopen ("/dev/tty", "w", stdout);
228     
229     sprintf (cmd, "grep \"[INFO]* INFO message: Silent mode.\" %s", stdout_tmp); 
230     
231     ret = system (cmd);
232     fail_if (ret == 0, cmd);
233     
234 END_TEST
235
236 /* Opens tcp server socket, listens for a connection, reads, and writes simple ack
237  * @param portno TCP port number of socket
238  * @param buffer Buffer to store data from client socket
239  * @param length Max length of data to read in buffer
240  * @param error Buffer to store error description in case of an error occurs
241  */
242 static void run_server_socket(int portno, char* buffer, int length, char* error) {
243     struct sockaddr_in serv_addr, cli_addr;
244     const char reply_message[] = "Message saved";
245     int serverfd = 0, clientfd = 0;
246     socklen_t clilen = 0;
247     int reuseaddr_option = 1;
248
249     serverfd = socket(AF_INET, SOCK_STREAM, 0);
250
251     if (serverfd > 0) {
252         memset(&serv_addr, 0, sizeof(serv_addr));
253         serv_addr.sin_family = AF_INET;
254         serv_addr.sin_addr.s_addr = INADDR_ANY;
255         serv_addr.sin_port = htons(portno);
256
257         /* Try to avoid "Address already in use" error from bind
258          * in case there is socket in state TIME_WAIT */
259         setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, 
260                    &reuseaddr_option, sizeof(reuseaddr_option));
261
262         if (bind(serverfd, (struct sockaddr *)&serv_addr,
263                  sizeof(serv_addr)) == 0) {
264             listen(serverfd, 5);
265             clilen = sizeof(cli_addr);
266             clientfd = accept(serverfd, (struct sockaddr *) &cli_addr, 
267                                &clilen);
268             if (clientfd > 0) {
269                 if (read(clientfd, buffer, length) < 0) {
270                     strcpy(error, strerror(errno));
271                 }
272
273                 /* create a dummy reply, the same as from CITA */
274                 write(clientfd, reply_message, strlen(reply_message));
275                 close(clientfd);
276             } else {
277                 strcpy(error, strerror(errno));
278             }
279         } else {
280             strcpy(error, strerror(errno));
281         }
282
283     } else {
284         strcpy(error, strerror(errno));
285     }
286
287     if (serverfd > 0) {
288         close(serverfd);
289     }
290 }
291
292 START_TEST (test_remote_logging)
293 {
294     testrunner_lite_options opts;
295     char buffer[1024];
296     char error[128];
297     const char sample_message[] = "Remote logger test data";
298     const char logger[] = "127.0.0.1";
299     pid_t pid = 0;
300
301     fail_if((pid = fork()) < 0);
302
303     if (pid == 0) {
304         /* child process to generate a log message */
305         memset (&opts, 0, sizeof(testrunner_lite_options));
306         opts.log_level = LOG_LEVEL_INFO;
307         opts.remote_logger = malloc(strlen(logger)+1);
308         strcpy(opts.remote_logger, logger);
309
310         /* wait for parent's server socket to be opened */
311         usleep(200000);
312
313         log_init(&opts);
314         LOG_MSG(LOG_INFO, "%s", sample_message);
315         log_close();
316
317         free(opts.remote_logger);
318         exit(0);
319     }
320
321     memset(buffer, 0, sizeof(buffer));
322     memset(error, 0, sizeof(error));
323
324     run_server_socket(80, buffer, sizeof(buffer) - 1, error);
325
326     /* wait child terminates */
327     wait(NULL);
328
329     fail_if(strlen(error) > 0, error);
330
331     /* Check that buffer contains at least something we expected */
332     fail_if(strstr(buffer, "HTTP") == NULL);
333     fail_if(strstr(buffer, sample_message) == NULL);
334 }
335 END_TEST
336
337 START_TEST (test_remote_logging_command)
338 {
339     char buffer[1024];
340     char error[128];
341     char logger_option[128];
342     int portno = 5678;
343     pid_t pid = 0;
344
345     fail_if((pid = fork()) < 0);
346
347     if (pid == 0) {
348         /* child process to run testrunner-lite with --logger option */
349
350         /* wait for parent's server socket to be opened */
351         usleep(200000);
352
353         sprintf(logger_option, "--logger=http://127.0.0.1:%d", portno);
354
355         execl(TESTRUNNERLITE_BIN,
356               TESTRUNNERLITE_BIN,
357               "-f", TESTDATA_SIMPLE_XML_1,
358               "-o", "/tmp/loggertestout.xml",
359               "-v",
360               logger_option,
361               (char*)NULL);
362         /* should never reach this point */
363         exit(1);
364     }
365
366     memset(buffer, 0, sizeof(buffer));
367     memset(error, 0, sizeof(error));
368
369     run_server_socket(portno, buffer, sizeof(buffer) - 1, error);
370
371     /* wait child terminates */
372     wait(NULL);
373
374     fail_if(strlen(error) > 0, error);
375
376     /* Check that buffer contains at least something we expected */
377     fail_if(strstr(buffer, "HTTP") == NULL);
378     fail_if(strstr(buffer, "levelname") == NULL);
379 }
380 END_TEST
381
382 START_TEST (test_hwinfo)
383      
384      hw_info hi;
385      testrunner_lite_options opts;
386
387      memset (&opts, 0x0, sizeof (opts));
388      executor_init (&opts);
389
390      memset (&hi, 0x0, sizeof (hw_info));
391      fail_if (read_hwinfo(&hi));
392               
393      print_hwinfo (&hi);
394
395      clean_hwinfo (&hi);
396     
397 END_TEST
398
399 /* ------------------------------------------------------------------------- */
400 /* ======================== FUNCTIONS ====================================== */
401 /* ------------------------------------------------------------------------- */
402 Suite *make_features_suite (void)
403 {
404     /* Create suite. */
405     Suite *s = suite_create ("tests for various testrunner-lite features");
406
407     /* Create test cases and add to suite. */
408     TCase *tc;
409
410     tc = tcase_create ("Test stripping of ctrl chars.");
411     tcase_set_timeout(tc, 600);
412     tcase_add_test (tc, test_ctrl_char_strip);
413     suite_add_tcase (s, tc);
414
415     tc = tcase_create ("Test logging.");
416     tcase_add_test (tc, test_logging);
417     suite_add_tcase (s, tc);
418
419     tc = tcase_create ("Test remote logging.");
420     tcase_add_test (tc, test_remote_logging);
421     suite_add_tcase (s, tc);
422
423     tc = tcase_create ("Test remote logging command.");
424     tcase_add_test (tc, test_remote_logging_command);
425     suite_add_tcase (s, tc);
426
427     tc = tcase_create ("Test hw info.");
428     tcase_add_test (tc, test_hwinfo);
429     suite_add_tcase (s, tc);
430
431     return s;
432 }
433
434 /* ================= OTHER EXPORTED FUNCTIONS ============================== */
435 /* None */
436
437 /* ------------------------------------------------------------------------- */
438 /* End of file */