Fix for coding rule
[platform/core/api/sound-pool.git] / test / sound_pool_test.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "logger.h"
18 #include "proxy.h"
19
20 #include <string.h>
21 #include <stdio.h>
22 #include <termios.h>
23 #include <unistd.h>
24 #include <getopt.h>
25
26 #define KEY_CODE_ESCAPE      27
27 #define KEY_CODE_BACKSPACE   127
28 #define KEY_CODE_TAB         9
29 #define KEY_CODE_ARROW_UP    65
30 #define KEY_CODE_ARROW_DOWN  66
31 #define KEY_CODE_ARROW_RIGHT 67
32 #define KEY_CODE_ARROW_LEFT  68
33
34 /* The list data structure to keep history of the test suite commands */
35 typedef struct __cmd_history_s {
36         struct __cmd_history_s *prev;
37         struct __cmd_history_s *next;
38         char cmd[MAX_COMMAND_LINE_LEN];
39 } _cmd_history_t;
40
41 static _cmd_history_t *_cmd_history_tail = NULL;
42 static _cmd_history_t *_cmd_history_curp = NULL;
43 static char OUTPUT_LOG_FILE[MAX_PATH_LEN] = "out.log";
44
45 void print_usage()
46 {
47         printf("Usage: sound_pool_test [options]                              \n");
48         printf("Test Suite for testing Tizen SoundPool module                 \n");
49         printf("-h, --help             - shows this help;                     \n");
50         printf("-s, --script=SCRIPT    - executes commands from the text file \n"
51                         "                         directly after start;                \n");
52         printf("-t, --target=TARGET(S) - selects the target or targets to     \n"
53                         "                         output logs. Possible targets are:   \n"
54                         "                         stderr, dlog, file. You can also     \n"
55                         "                         select multiple targets using coma.  \n"
56                         "                         for example,                         \n"
57                         "                         > sound_pool_test -t stderr,file     \n"
58                         "                         will output both in standard         \n"
59                         "                         error and file;                      \n");
60         printf("-f, --file=FILEPATH    - selects file for file output logging.\n"
61                         "                         Works only in -t argument value      \n"
62                         "                         includes 'file' target;              \n");
63 }
64
65 _cmd_history_t *add_cmd_to_history(const char *cmd)
66 {
67         if (!cmd)
68                 return NULL;
69
70         if (!_cmd_history_tail) {
71                 _cmd_history_tail = malloc(sizeof(_cmd_history_t));
72                 if (!_cmd_history_tail)
73                         return NULL;
74                 _cmd_history_tail->prev = NULL;
75                 _cmd_history_tail->next = NULL;
76         } else {
77                 _cmd_history_tail->next = malloc(sizeof(_cmd_history_t));
78                 if (!_cmd_history_tail->next)
79                         return NULL;
80                 _cmd_history_tail->next->prev = _cmd_history_tail;
81                 _cmd_history_tail->next->next = NULL;
82                 _cmd_history_tail = _cmd_history_tail->next;
83         }
84
85         strncpy(_cmd_history_tail->cmd, cmd, MAX_COMMAND_LINE_LEN - 1);
86         _cmd_history_tail->cmd[MAX_COMMAND_LINE_LEN - 1] = '\0';
87         _cmd_history_curp = _cmd_history_tail;
88         return _cmd_history_tail;
89 }
90
91 const char *pop_up_curp_from_cmd_history()
92 {
93         if (!_cmd_history_curp)
94                 return NULL;
95
96         const char *curp_cmd = _cmd_history_curp->cmd;
97         if (_cmd_history_curp->prev)
98                 _cmd_history_curp = _cmd_history_curp->prev;
99         return curp_cmd;
100 }
101
102 const char *pop_down_curp_from_cmd_history()
103 {
104         if (!_cmd_history_curp)
105                 return NULL;
106
107         const char *curp_cmd = _cmd_history_curp->cmd;
108         if (_cmd_history_curp->next)
109                 _cmd_history_curp = _cmd_history_curp->next;
110         return curp_cmd;
111 }
112
113 /* Searches the same part of two strings from the start and returns the length
114    of this part. For example, for the strings "Big Troll" and "Big troll" value
115    4 will be returned (the same part is "Big "). */
116 size_t get_identical_start_len(const char *str1, const char *str2)
117 {
118         size_t len1 = strnlen(str1, MAX_COMMAND_LINE_LEN);
119         size_t len2 = strnlen(str2, MAX_COMMAND_LINE_LEN);
120         size_t idx = 0;
121         while (idx < len1 && idx < len2) {
122                 if (str1[idx] != str2[idx])
123                         break;
124                 ++idx;
125         }
126         return idx;
127 }
128
129 size_t auto_fill(const char *cmd_start, char fill_hint[MAX_COMMAND_LINE_LEN])
130 {
131         size_t idx = 0;
132         size_t cmd_start_len = strnlen(cmd_start, MAX_COMMAND_LINE_LEN);
133
134         char auto_fill[MAX_COMMAND_LINE_LEN] = { '\0' };
135         size_t fill_found = 0;
136
137         for (; idx < CMD_COUNT; ++idx) {
138                 if (strncmp(cmd_start, cmd_list[idx], cmd_start_len) == 0) {
139                         if (!fill_found) {
140                                 strncpy(auto_fill, cmd_list[idx], MAX_COMMAND_LINE_LEN);
141                                 fill_found = strnlen(auto_fill, MAX_COMMAND_LINE_LEN);
142                         } else {
143                                 fill_found = get_identical_start_len(auto_fill, cmd_list[idx]);
144                                 auto_fill[fill_found] = '\0';
145                         }
146                 }
147         }
148
149         if (!fill_found)
150                 strncpy(fill_hint, cmd_start, MAX_COMMAND_LINE_LEN);
151         else
152                 strncpy(fill_hint, auto_fill, MAX_COMMAND_LINE_LEN);
153
154         return fill_found;
155 }
156
157 size_t print_cmd_prompt()
158 {
159         const char *prompt = "sound-pool-ts-cmd > ";
160         printf("%s", prompt);
161         /* Return the length of comand prompt c-string */
162         return strnlen(prompt, MAX_COMMAND_LINE_LEN);
163 }
164
165 int getch(void)
166 {
167         struct termios oldattr, newattr;
168         int ch;
169         tcgetattr(STDIN_FILENO, &oldattr);
170         newattr = oldattr;
171         newattr.c_lflag &= ~(ICANON | ECHO);
172         tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
173         ch = getchar();
174         tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
175         return ch;
176 }
177
178 size_t ts_getline(char *cmd_line)
179 {
180         if (!cmd_line)
181                 return 0;
182
183         print_cmd_prompt();
184
185         /* Read whole line */
186         int ci = 0;
187         char cc = '\0';
188         int c = 0;
189         while ((c = getch()) != EOF && (cc = (char)c) != '\n' &&
190                         ci < MAX_COMMAND_LINE_LEN - 1) {
191                 if (cc == KEY_CODE_ESCAPE) { /* Arrow keys */
192                         getch();
193                         c = getch();
194                         if (c == EOF)
195                                 continue;
196                         cc = (char)c; /* Here is particular arrow code */
197                         const char *curp_cmd = NULL;
198                         if (cc == KEY_CODE_ARROW_UP) {
199                                 if ((curp_cmd = pop_up_curp_from_cmd_history())) {
200                                         while (ci-- != 0)
201                                                 printf("\b \b");
202                                         printf("%s", curp_cmd);
203                                         strncpy(cmd_line, curp_cmd, MAX_COMMAND_LINE_LEN);
204                                         ci = strnlen(curp_cmd, MAX_COMMAND_LINE_LEN);
205                                 }
206                         } else if (cc == KEY_CODE_ARROW_DOWN) {
207                                 if ((curp_cmd = pop_down_curp_from_cmd_history())) {
208                                         while (ci-- != 0)
209                                                 printf("\b \b");
210                                         printf("%s", curp_cmd);
211                                         strncpy(cmd_line, curp_cmd, MAX_COMMAND_LINE_LEN);
212                                         ci = strnlen(curp_cmd, MAX_COMMAND_LINE_LEN);
213                                 }
214                         }
215                         continue;
216                 }
217                 if (cc == KEY_CODE_BACKSPACE) { /* Backspace key */
218                         if (ci != 0) {
219                                 printf("\b \b");
220                                 cmd_line[ci--] = '\0';
221                         }
222                         continue;
223                 }
224                 if (cc == KEY_CODE_TAB) { /* Tab key */
225                         size_t hint_len = auto_fill(cmd_line, cmd_line);
226                         while (ci < hint_len)
227                                 printf("%c", cmd_line[ci++]);
228                         cmd_line[ci] = '\0';
229                         continue;
230                 }
231                 cmd_line[ci++] = cc;
232                 cmd_line[ci] = '\0';
233                 printf("%c", cc);
234         }
235
236         printf("\n");
237
238         return ci + 1;
239 }
240
241 int main(int argc, char* argv[])
242 {
243         _logger_set_log_tag("TIZEN_SOUND_POOL_TEST_SUITE");
244         _logger_set_logging_mode(LOG_MODE_STDERR | LOG_MODE_DLOG);
245
246 #   define OPTIONS "s:f:t:h"
247         struct option options[] = {
248                 { "script",  required_argument, NULL, 's' },
249                 { "logfile", required_argument, NULL, 'f' },
250                 { "target",  required_argument, NULL, 't' },
251                 { "help",    no_argument,       NULL, 'h' },
252                 { NULL, 0, NULL, 0 }
253         };
254
255         char commands[MAX_COMMAND_LINE_LEN] = { '\0' };
256         size_t last_cmd_end = 0;
257
258         int opt = 0;
259         int do_print_usage = 0;
260         int do_set_file = 0;
261         while ((opt = getopt_long(argc, argv, OPTIONS, options, NULL)) != -1) {
262                 switch (opt) {
263                 case 's': {
264                         snprintf(commands + last_cmd_end, MAX_COMMAND_LINE_LEN,
265                                         "%s %s\n", CMD_EXECUTE_SCRIPT, optarg);
266                         last_cmd_end +=
267                                         strnlen(commands + last_cmd_end, MAX_COMMAND_LINE_LEN) + 1;
268                         break;
269                 }
270                 case 'f': {
271                         _logger_set_file(optarg);
272                         do_set_file--;
273                         break;
274                 }
275                 case 't': {
276                         int log_mode = LOG_MODE_NONE;
277                         char *token = strtok(optarg, ",");
278
279                         while (token != NULL) {
280                                 if (strncmp(token, "stderr", MAX_MSG_LEN) == 0) {
281                                         log_mode |= LOG_MODE_STDERR;
282                                 } else if (strncmp(token, "file", MAX_MSG_LEN) == 0) {
283                                         log_mode |= LOG_MODE_FILE;
284                                         do_set_file++;
285                                 } else if (strncmp(token, "dlog", MAX_MSG_LEN) == 0) {
286                                         log_mode |= LOG_MODE_DLOG;
287                                 } else {
288                                         _printf(CMD_COLOR_RED, "%s target is not supported! "
289                                                         "Use one (or combination separated by coma) "
290                                                         "from the list: dlog, stderr, and dlog.\n", token);
291                                 }
292                                 token = strtok(NULL, ", ");
293                         }
294
295                         if (log_mode != LOG_MODE_NONE)
296                                 _logger_set_logging_mode(log_mode);
297                         break;
298                 }
299                 case 'h':
300                 case '?': {
301                         do_print_usage = 1;
302                         break;
303                 }
304                 default:
305                         break;
306                 }
307         }
308
309         if (do_print_usage != 0)
310                 print_usage();
311
312         if (do_set_file > 0)
313                 _logger_set_file(OUTPUT_LOG_FILE);
314
315         char *ccmd = commands;
316
317         while (ccmd[0] != '\0') {
318                 if (_exec_cmd(ccmd) == UCMD) {
319                         _printf(CMD_COLOR_RED,
320                                         "Unknown command! Type 'help' for command help!\n");
321                 }
322                 ccmd += strnlen(ccmd, MAX_COMMAND_LINE_LEN) + 1;
323         }
324
325         char cmd_line[MAX_COMMAND_LINE_LEN];
326         size_t cmd_line_len = 0;
327
328         while ((cmd_line_len = ts_getline(cmd_line))) {
329                 if (cmd_line_len == 1)
330                         continue;
331
332                 /* Try to execute commands parsed from the line: */
333                 int res = _exec_cmd(cmd_line);
334                 if (res == EXIT)
335                         break;
336
337                 if (res == UCMD)
338                         _printf(CMD_COLOR_RED,
339                                         "Unknown command! Type 'help' for command help!\n");
340
341                 add_cmd_to_history(cmd_line);
342         }
343
344         return 0;
345 }