Add new api of stream and instance for multi-instance
[platform/core/multimedia/mm-resource-manager.git] / test / mm_res_manager_test.c
1 /*
2  * Copyright (c) 2017 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 <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <glib.h>
21
22 #include "lib/mm_resource_manager.h"
23
24
25
26 typedef enum {
27         TEST_COMMAND_CREATE = 'c',
28         TEST_COMMAND_DESTROY = 'd',
29         TEST_COMMAND_MARK_ACQUIRE = 'a',
30         TEST_COMMAND_MARK_RELEASE = 'r',
31         TEST_COMMAND_MARK_RELEASE_ALL = 'R',
32         TEST_COMMAND_MARK_RESIZE = 's',
33         TEST_COMMAND_COMMIT = 'm',
34         TEST_COMMAND_APP_CLASS_LIST = 'p',
35         TEST_COMMAND_RES_TYPE_LIST = 't',
36         TEST_COMMAND_RES_TYPE_COND_LIST = 'n',
37         TEST_COMMAND_STATUS = 'u'
38 } test_command_e;
39
40 typedef enum {
41         MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE,   /* uncommitted */
42         MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED,      /* committed   */
43         MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE    /* uncommitted */
44 } mm_resource_manager_res_state_e;
45
46
47
48 #define MAX_CMD_LINE_LEN 80
49 #define INDENT 4
50 #define GET_ENUM_STR(val, str_a) \
51         ((val >= 0 && val < sizeof(str_a) / sizeof(str_a[0])) ? str_a[val] : "(!)unknown")
52
53
54
55 static const char *resource_str[MM_RESOURCE_MANAGER_RES_TYPE_MAX + 1] = {
56         "video_decoder(#0)",
57         "video_overlay(#1)",
58         "camera(#2)",
59         "video_encoder(#3)",
60         "radio(#4)",
61         "audio_offload(#5)",
62         NULL
63 };
64
65 static const char *app_class_str[MM_RESOURCE_MANAGER_APP_CLASS_MAX + 1] = {
66         "media",
67         "interrupt",
68         NULL
69 };
70
71 static const char *status_str[MM_RESOURCE_MANAGER_STATUS_MAX + 1] = {
72         "disconnected",
73         NULL
74 };
75
76 static const char *condition_str[MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX + 1] = {
77         "SD",
78         "HD",
79         "FHD",
80         "UHD",
81         NULL
82 };
83
84 static const char *res_state_str[MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE + 2] = {
85         "FOR ACQUIRE",
86         "ACQUIRED",
87         "FOR RELEASE",
88         NULL
89 };
90
91
92
93 static GMainLoop *loop;
94 static GHashTable *resource_managers;
95 static gboolean auto_destroy_manager = TRUE;
96 static GMutex sync_mutex;
97 static gboolean skip_menu = FALSE;
98
99
100
101 static void print_api_error(char *msg, mm_resource_manager_error_e err)
102 {
103         char *err_str;
104
105         switch (err) {
106         case MM_RESOURCE_MANAGER_ERROR_NONE:
107                 err_str = "no error";
108                 break;
109         case MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER:
110                 err_str = "invalid parameter";
111                 break;
112         case MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION:
113                 err_str = "invalid operation";
114                 break;
115         case MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED:
116                 err_str = "not supported";
117                 break;
118         case MM_RESOURCE_MANAGER_ERROR_INVALID_STATE:
119                 err_str = "invalid state";
120                 break;
121         case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY:
122                 err_str = "low priority";
123                 break;
124         case MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH:
125                 err_str = "not enough volume";
126                 break;
127         default:
128                 err_str = "unknown error";
129         }
130
131         g_print("API ERROR: %d (%s) - %s", err, err_str, msg);
132 }
133
134 static void print_error(char *msg)
135 {
136         g_print("ERROR: %s", msg);
137 }
138
139 static int release_cb(mm_resource_manager_h rm,
140                 mm_resource_manager_res_h resource_h, void *user_data)
141 {
142         GHashTable *resources;
143
144         g_print("Release cb of resource manager %p is called for resource "
145                         "%p\n", rm, resource_h);
146
147         g_mutex_lock(&sync_mutex);
148         resources = g_hash_table_lookup(resource_managers, rm);
149         if (resources)
150                 g_hash_table_remove(resources, resource_h);
151         else
152                 g_print("WARNING: resource manager %p was removed during the release cb call. Nothing is done.", rm);
153         g_mutex_unlock(&sync_mutex);
154         return FALSE;
155 }
156
157 static void status_cb(mm_resource_manager_h rm, mm_resource_manager_status_e status,
158                 void *user_data)
159 {
160         g_print("Status cb of resource manager %p is called with status %d (%s)\n",
161                         rm, status, status_str[status]);
162
163         g_mutex_lock(&sync_mutex);
164         if (g_hash_table_lookup(resource_managers, rm)) {
165
166                 switch (status) {
167                 case MM_RESOURCE_MANAGER_STATUS_DISCONNECTED:
168                         g_print("Resource manager %p cannot be used anymore and must be"
169                                         " destroyed.\n", rm);
170                         break;
171                 default:
172                         break;
173                 }
174         } else {
175                 g_print("WARNING: resource manager %p was removed during the status "
176                                 "cb call.", rm);
177         }
178         g_mutex_unlock(&sync_mutex);
179 }
180
181 static int get_max_str_len(const char *strs[])
182 {
183         int i;
184         int len;
185         int max_len = 0;
186
187         for (i = 0; strs[i]; i++) {
188                 len = strlen(strs[i]);
189                 if (max_len < len)
190                         max_len = len;
191         }
192
193         return max_len;
194 }
195
196 static int counter(gboolean reset)
197 {
198         static int counter = 1;
199         if (reset) {
200                 counter = 1;
201                 return counter;
202         } else {
203                 return counter++;
204         }
205 }
206
207 static void display_menu_head(gchar *title)
208 {
209         int i;
210
211         g_print("\n");
212         for (i = 0; i < MAX_CMD_LINE_LEN; i++)
213                 g_print("=");
214         g_print("\n   %s\n", title);
215         for (i = 0; i < MAX_CMD_LINE_LEN; i++)
216                 g_print("-");
217         g_print("\n");
218 }
219
220 static void display_menu_tail(gboolean input)
221 {
222         int i;
223
224         for (i = 0; i < MAX_CMD_LINE_LEN; i++)
225                 g_print("-");
226         g_print("\n");
227         for (i = 0; i < MAX_CMD_LINE_LEN; i++)
228                 g_print("=");
229         g_print("\n");
230         if (input)
231                 g_print(">");
232 }
233
234 static void display_app_classes()
235 {
236         int i;
237
238         display_menu_head("Application Classes");
239
240         for (i = 0; i < MM_RESOURCE_MANAGER_APP_CLASS_MAX; i++)
241                 g_print("%d - %s\n", i, app_class_str[i]);
242
243         display_menu_tail(FALSE);
244 }
245
246 static gpointer get_manager_by_index(int i)
247 {
248         gpointer man;
249         gpointer *mans;
250         guint len;
251
252         mans = g_hash_table_get_keys_as_array(resource_managers, &len);
253
254         man = i < len ? mans[i] : NULL;
255
256         g_free(mans);
257
258         return man;
259 }
260
261 static mm_resource_manager_h get_manager_from_cmd(gchar **cmd_tokens)
262 {
263         mm_resource_manager_h rm;
264         int manager_i;
265
266         if (!cmd_tokens[1]) {
267                 print_error("Resource manager number was not specified");
268                 return NULL;
269         }
270
271         manager_i = g_ascii_strtoull(cmd_tokens[1], NULL, 10);
272         if (!manager_i && g_strcmp0(cmd_tokens[1], "0")) {
273                 print_error("Resource manager number is not unsigned integer");
274                 return NULL;
275         }
276
277         rm = get_manager_by_index(manager_i - 1);
278         if (!rm) {
279                 print_error("Resource manager number is out of bounds");
280                 return NULL;
281         }
282
283         return rm;
284 }
285
286 static void display_resource_types(gchar **cmd_tokens)
287 {
288         int i;
289         mm_resource_manager_res_volume volume;
290         mm_resource_manager_h rm;
291         static int max_res_len = 0;
292
293         if (!max_res_len)
294                 max_res_len = get_max_str_len(resource_str);
295
296         rm = get_manager_from_cmd(cmd_tokens);
297         if (!rm)
298                 return;
299
300         display_menu_head("Resource Types (Max Volume)");
301
302         for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
303                 mm_resource_manager_get_res_type_max_volume(rm, i, &volume);
304                 g_print("%d - %*s %d\n", i, max_res_len, resource_str[i], volume);
305         }
306
307         display_menu_tail(FALSE);
308 }
309
310 static void display_conditions(gchar **cmd_tokens)
311 {
312         int i, j;
313         int align;
314         mm_resource_manager_res_volume volume;
315         static int max_cond_width = 0;
316         static int max_res_width = 0;
317         mm_resource_manager_h rm;
318
319         rm = get_manager_from_cmd(cmd_tokens);
320         if (!rm)
321                 return;
322
323         if (!max_cond_width) {
324                 max_res_width = get_max_str_len(resource_str);
325                 align = (MAX_CMD_LINE_LEN - max_res_width) / MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX;
326                 max_cond_width = get_max_str_len(condition_str);
327                 if (align > max_cond_width)
328                         max_cond_width = align;
329         }
330
331         display_menu_head("Resource Conditions");
332
333         g_print("%*s", max_res_width, "type/cond");
334         for (j = 0; j < MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX; j++)
335                 g_print("%*s", max_cond_width, condition_str[j]);
336
337         g_print("\n");
338
339         for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
340                 g_print("%*s", max_res_width, resource_str[i]);
341                 for (j = 0; j < MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX; j++) {
342                         if (mm_resource_manager_get_res_type_volume(rm, i, j, &volume) ==
343                                         MM_RESOURCE_MANAGER_ERROR_NONE)
344                                 g_print("%*d", max_cond_width, volume);
345                         else
346                                 g_print("%*s", max_cond_width, "-");
347                 }
348                 g_print("\n");
349         }
350
351         display_menu_tail(FALSE);
352 }
353
354 static void display_manager_resource(gpointer resource, gpointer state,
355                 gpointer user_data)
356 {
357         mm_resource_manager_h rm = user_data;
358         mm_resource_manager_res_h res = resource;
359         mm_resource_manager_res_info_s res_info;
360
361         g_print("%*d.%*s", INDENT, counter(FALSE), INDENT, " ");
362         if (mm_resource_manager_get_resource_info(rm, res, &res_info) ==
363                         MM_RESOURCE_MANAGER_ERROR_NONE) {
364                 g_print("%p %s (%s, %d, %s)\n", res,
365                                 GET_ENUM_STR(*((mm_resource_manager_res_state_e*)state), res_state_str),
366                                 GET_ENUM_STR(res_info.type, resource_str),
367                                 res_info.volume, res_info.is_acquire_failed ? "TRUE" : "FALSE");
368         } else {
369                 g_print("(!) Can't get resource info\n");
370         }
371 }
372
373 static void display_manager(gpointer manager, gpointer resources, gpointer user_data)
374 {
375         int *number_p = user_data;
376
377         if (g_hash_table_size(resources)) {
378                 g_print("%d. manager %p resources:\n", (*number_p)++, manager);
379                 counter(TRUE);
380                 g_hash_table_foreach(resources, display_manager_resource, manager);
381         } else {
382                 g_print("%d. manager %p\n", (*number_p)++, manager);
383         }
384 }
385
386 static void display_manager_list()
387 {
388         int number = 1;
389
390         display_menu_head("Existing Resource Managers");
391         g_mutex_lock(&sync_mutex);
392         g_hash_table_foreach(resource_managers, display_manager, &number);
393         g_mutex_unlock(&sync_mutex);
394         display_menu_tail(FALSE);
395 }
396
397 static void display_menu()
398 {
399         if (skip_menu)
400                 return;
401
402         display_menu_head("MM Resource Manager Test Suite: Main menu");
403
404         /*
405          * <app class> - int value of mm_resource_manager_app_class_e
406          * <manager number> - number returned by the status command
407          * <numeric resource type> - int value of mm_resource_manager_res_type_e
408          * <volume> - int value; -1 means full volume of resource
409          * <resource number> - number returned by the status command
410          */
411         g_print("c - Create Resource Manager <app class>\n");
412         g_print("d - Destroy Resource Manager <manager number>\n");
413         g_print("a - Mark For Acquire <manager number> <numeric resource type> <volume>\n");
414         g_print("r - Mark For Release <manager number> <resource number>\n");
415         g_print("R - Mark All For Release <manager number>\n");
416         g_print("s - Resize Marked <manager number> <resource number> <volume>\n");
417         g_print("m - Commit <manager number>\n");
418         g_print("p - Print Application Classes\n");
419         g_print("t - Print Resource Types <manager number>\n");
420         g_print("n - Print Resource Conditions <manager number>\n");
421         g_print("u - Print Resource Manager List and Status\n");
422         g_print("q - Quit\n");
423
424         display_menu_tail(TRUE);
425 }
426
427 static gpointer get_resource_by_index(mm_resource_manager_h rm, int i)
428 {
429         gpointer res;
430         gpointer *reses;
431         guint len;
432
433         reses = g_hash_table_get_keys_as_array(g_hash_table_lookup(resource_managers, rm), &len);
434
435         res = i < len ? reses[i] : NULL;
436
437         g_free(reses);
438
439         return res;
440 }
441
442 static mm_resource_manager_res_h get_resource_from_cmd(gchar **cmd_tokens, mm_resource_manager_h rm)
443 {
444         mm_resource_manager_res_h res;
445         int res_i;
446
447         if (!cmd_tokens[2]) {
448                 print_error("Resource number was not specified");
449                 return NULL;
450         }
451
452         res_i = g_ascii_strtoull(cmd_tokens[2], NULL, 10);
453         if (!res_i && g_strcmp0(cmd_tokens[2], "0")) {
454                 print_error("Resource number is not unsigned integer");
455                 return NULL;
456         }
457
458         res = get_resource_by_index(rm, res_i - 1);
459         if (!res) {
460                 print_error("Resource number is out of bounds");
461                 return NULL;
462         }
463
464         return res;
465 }
466
467 static gboolean get_resource_type_from_cmd(gchar **cmd_tokens, int *res_p)
468 {
469         if (!cmd_tokens[2]) {
470                 print_error("Resource was not specified");
471                 return FALSE;
472         }
473
474         *res_p = g_ascii_strtoull(cmd_tokens[2], NULL, 10);
475         if (!*res_p && g_strcmp0(cmd_tokens[2], "0")) {
476                 print_error("Resource is not integer");
477                 return FALSE;
478         }
479
480         return TRUE;
481 }
482
483 static gboolean get_volume_from_cmd(gchar **cmd_tokens, int *res_p)
484 {
485         if (!cmd_tokens[3]) {
486                 print_error("Resource volume was not specified");
487                 return FALSE;
488         }
489
490         *res_p = g_ascii_strtoull(cmd_tokens[3], NULL, 10);
491         if (!*res_p && g_strcmp0(cmd_tokens[3], "0")) {
492                 print_error("Resource volume is not integer");
493                 return FALSE;
494         }
495
496         return TRUE;
497 }
498
499 static void free_resource_state(void *res_state_p)
500 {
501         g_free(res_state_p);
502 }
503
504 static void process_create_cmd(gchar **cmd_tokens)
505 {
506         int app_class;
507         mm_resource_manager_error_e err;
508         mm_resource_manager_h rm;
509
510         if (!cmd_tokens[1]) {
511                 print_error("Application class was not specified");
512                 return;
513         }
514
515         app_class = g_ascii_strtoull(cmd_tokens[1], NULL, 10);
516         if (!app_class && g_strcmp0(cmd_tokens[1], "0")) {
517                 print_error("Application class is not unsigned integer");
518                 return;
519         }
520
521         err = mm_resource_manager_create(app_class, release_cb, NULL, &rm);
522         if (err == MM_RESOURCE_MANAGER_ERROR_NONE) {
523                 if (mm_resource_manager_set_status_cb(rm, status_cb, NULL) ==
524                                 MM_RESOURCE_MANAGER_ERROR_NONE) {
525                         g_mutex_lock(&sync_mutex);
526                         g_hash_table_insert(resource_managers, rm,
527                                         g_hash_table_new_full(NULL, NULL, NULL, free_resource_state));
528                         g_mutex_unlock(&sync_mutex);
529                         g_print("Resource manager %p of class '%s' created successfully\n",
530                                         rm, GET_ENUM_STR(app_class, app_class_str));
531                 } else {
532                         mm_resource_manager_destroy(rm);
533                         print_api_error("Resource manager couldn't be created. "
534                                         "Could not set callbacks", err);
535                 }
536         } else {
537                 print_api_error("Resource manager couldn't be created", err);
538         }
539 }
540
541 static void process_destroy_cmd(gchar **cmd_tokens)
542 {
543         mm_resource_manager_error_e err;
544         mm_resource_manager_h rm;
545
546         rm = get_manager_from_cmd(cmd_tokens);
547         if (!rm)
548                 return;
549
550         err = mm_resource_manager_destroy(rm);
551         if (err == MM_RESOURCE_MANAGER_ERROR_NONE) {
552                 g_mutex_lock(&sync_mutex);
553                 auto_destroy_manager = FALSE;
554                 g_hash_table_remove(resource_managers, rm);
555                 auto_destroy_manager = TRUE;
556                 g_mutex_unlock(&sync_mutex);
557                 g_print("Resource manager %p destroyed successfully\n", rm);
558         } else {
559                 print_api_error("Resource manager couldn't be destroyed", err);
560         }
561 }
562
563 static void process_mark_for_acquire_cmd(gchar **cmd_tokens)
564 {
565         mm_resource_manager_error_e err;
566         mm_resource_manager_h rm;
567         mm_resource_manager_res_h res_h;
568         mm_resource_manager_res_volume volume;
569         int resource;
570
571         rm = get_manager_from_cmd(cmd_tokens);
572         if (!rm)
573                 return;
574
575         if (!get_resource_type_from_cmd(cmd_tokens, &resource))
576                 return;
577
578         if (!get_volume_from_cmd(cmd_tokens, &volume))
579                 return;
580
581         err = mm_resource_manager_mark_for_acquire(rm, resource, volume, &res_h);
582         if (err == MM_RESOURCE_MANAGER_ERROR_NONE) {
583                 const char *res_name = GET_ENUM_STR(resource, resource_str);
584
585                 g_mutex_lock(&sync_mutex);
586                 g_hash_table_insert(g_hash_table_lookup(resource_managers, rm),
587                                 res_h, g_new0(mm_resource_manager_res_state_e, 1));
588                 g_mutex_unlock(&sync_mutex);
589
590                 g_print("Resource '%s' of volume %d is marked for acquire in RM %p successfully\n",
591                                 res_name, volume, rm);
592         } else {
593                 print_api_error("Resource couldn't be marked for acquire", err);
594         }
595 }
596
597 static void process_mark_for_release_cmd(gchar **cmd_tokens)
598 {
599         mm_resource_manager_error_e err;
600         mm_resource_manager_h rm;
601         mm_resource_manager_res_h resource;
602         mm_resource_manager_res_state_e *state_p;
603         GHashTable *resources;
604
605         rm = get_manager_from_cmd(cmd_tokens);
606         if (!rm)
607                 return;
608
609         resource = get_resource_from_cmd(cmd_tokens, rm);
610         if (!resource)
611                 return;
612
613         g_mutex_lock(&sync_mutex);
614         resources = g_hash_table_lookup(resource_managers, rm);
615         state_p = (mm_resource_manager_res_state_e *)g_hash_table_lookup(resources, resource);
616         err = mm_resource_manager_mark_for_release(rm, resource);
617         if (err == MM_RESOURCE_MANAGER_ERROR_NONE) {
618
619                 if (*state_p == MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE)
620                         g_hash_table_remove(resources, resource);
621                 else
622                         *state_p = MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
623
624                 g_print("Resource handle %p is marked for release in RM %p successfully\n",
625                                 resource, rm);
626         } else {
627                 print_api_error("Resource manager couldn't mark resource for release", err);
628         }
629         g_mutex_unlock(&sync_mutex);
630 }
631
632 static gboolean is_marked_for_acquire(gpointer resource, gpointer state, gpointer user_data)
633 {
634         return *((mm_resource_manager_res_state_e *)state) == MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE;
635 }
636
637 static void mark_all_for_release(gpointer resource, gpointer state, gpointer user_data)
638 {
639         mm_resource_manager_res_state_e *state_p = (mm_resource_manager_res_state_e *)state;
640         if (*state_p == MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED)
641                 *state_p = MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
642 }
643
644 static void process_mark_for_release_all_cmd(gchar **cmd_tokens)
645 {
646         mm_resource_manager_error_e err;
647         mm_resource_manager_h rm;
648         GHashTable *resources;
649
650         rm = get_manager_from_cmd(cmd_tokens);
651         if (!rm)
652                 return;
653
654         err = mm_resource_manager_mark_all_for_release(rm);
655         if (err == MM_RESOURCE_MANAGER_ERROR_NONE) {
656
657                 g_mutex_lock(&sync_mutex);
658                 resources = g_hash_table_lookup(resource_managers, rm);
659                 g_hash_table_foreach(resources, mark_all_for_release, NULL);
660                 g_hash_table_foreach_remove(resources, is_marked_for_acquire, NULL);
661                 g_mutex_unlock(&sync_mutex);
662
663                 g_print("All resources are marked for release in RM %p successfully\n", rm);
664         } else {
665                 print_api_error("Resource manager couldn't mark resources for release", err);
666         }
667 }
668
669 static void process_resize_marked_cmd(gchar **cmd_tokens)
670 {
671         mm_resource_manager_error_e err;
672         mm_resource_manager_h rm;
673         mm_resource_manager_res_h res_h;
674         mm_resource_manager_res_volume volume;
675         mm_resource_manager_res_state_e *state;
676
677         rm = get_manager_from_cmd(cmd_tokens);
678         if (!rm)
679                 return;
680
681         res_h = get_resource_from_cmd(cmd_tokens, rm);
682         if (!res_h)
683                 return;
684
685         if (!get_volume_from_cmd(cmd_tokens, &volume))
686                 return;
687
688         err = mm_resource_manager_resize_marked(rm, res_h, volume);
689         if (err == MM_RESOURCE_MANAGER_ERROR_NONE) {
690
691                 g_mutex_lock(&sync_mutex);
692                 state = (mm_resource_manager_res_state_e *)g_hash_table_lookup(
693                                 g_hash_table_lookup(resource_managers, rm), res_h);
694                 *state = MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE;
695                 g_mutex_unlock(&sync_mutex);
696
697                 g_print("Resource handle %p is resized to volume %d and marked "
698                                 "for acquire in RM %p successfully\n", res_h, volume, rm);
699         } else {
700                 print_api_error("Resource couldn't be marked for acquire", err);
701         }
702 }
703
704 static void move_to_acquired(gpointer resource, gpointer state,
705                 gpointer user_data)
706 {
707         mm_resource_manager_res_state_e *res_state =
708                         (mm_resource_manager_res_state_e *)state;
709         if (*res_state == MM_RESOURCE_MANAGER_RES_STATE_FOR_ACQUIRE)
710                 *res_state = MM_RESOURCE_MANAGER_RES_STATE_ACQUIRED;
711 }
712
713 static gboolean is_marked_for_release(gpointer resource, gpointer state,
714                 gpointer user_data)
715 {
716         return *((mm_resource_manager_res_state_e *)state) ==
717                         MM_RESOURCE_MANAGER_RES_STATE_FOR_RELEASE;
718 }
719
720 static void process_commit_cmd(gchar **cmd_tokens)
721 {
722         mm_resource_manager_error_e err;
723         mm_resource_manager_h rm;
724         GHashTable *resources;
725
726         rm = get_manager_from_cmd(cmd_tokens);
727         if (!rm)
728                 return;
729
730         err = mm_resource_manager_commit(rm);
731         switch (err) {
732         case MM_RESOURCE_MANAGER_ERROR_NONE:
733                 g_mutex_lock(&sync_mutex);
734                 resources = g_hash_table_lookup(resource_managers, rm);
735                 g_hash_table_foreach(resources, move_to_acquired, NULL);
736                 g_hash_table_foreach_remove(resources, is_marked_for_release, NULL);
737                 g_mutex_unlock(&sync_mutex);
738
739                 g_print("Changes in RM %p were committed successfully\n", rm);
740                 break;
741         case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY:
742                 print_api_error("Commit couldn't be done because of resource conflict", err);
743                 break;
744         default:
745                 print_api_error("Commit couldn't be done", err);
746                 break;
747         }
748 }
749
750 static void process_app_class_list_cmd(gchar **cmd_tokens)
751 {
752         display_app_classes();
753 }
754
755 static void process_resource_type_list_cmd(gchar **cmd_tokens)
756 {
757         display_resource_types(cmd_tokens);
758 }
759
760 static void process_resource_type_condition_list_cmd(gchar **cmd_tokens)
761 {
762         display_conditions(cmd_tokens);
763 }
764
765 static void process_status_cmd(gchar **cmd_tokens)
766 {
767         display_manager_list();
768 }
769
770 static gboolean input(GIOChannel *channel)
771 {
772         gsize read_size;
773         GError *error = NULL;
774         gchar **cmd_tokens;
775         GString *cmd_line;
776
777         cmd_line = g_string_new(NULL);
778         if (g_io_channel_read_line_string(channel, cmd_line, &read_size, &error) != G_IO_STATUS_NORMAL)
779                 return TRUE;
780
781         g_strstrip(cmd_line->str);
782
783         if (g_strcmp0(cmd_line->str, "q") == 0) {
784                 g_string_free(cmd_line, TRUE);
785                 g_main_loop_quit(loop);
786                 return TRUE;
787         }
788
789         cmd_tokens = g_strsplit(cmd_line->str, " ", 0);
790
791         if (!cmd_tokens) {
792                 g_string_free(cmd_line, TRUE);
793                 g_print("Empty command\n");
794                 display_menu();
795
796                 return TRUE;
797         }
798
799         if (!cmd_tokens[0]) {
800                 g_string_free(cmd_line, TRUE);
801                 g_print("Empty command\n");
802                 g_strfreev(cmd_tokens);
803                 display_menu();
804
805                 return TRUE;
806         }
807
808         switch (cmd_tokens[0][0]) {
809         case TEST_COMMAND_CREATE:
810                 process_create_cmd(cmd_tokens);
811                 break;
812         case TEST_COMMAND_DESTROY:
813                 process_destroy_cmd(cmd_tokens);
814                 break;
815         case TEST_COMMAND_MARK_ACQUIRE:
816                 process_mark_for_acquire_cmd(cmd_tokens);
817                 break;
818         case TEST_COMMAND_MARK_RELEASE:
819                 process_mark_for_release_cmd(cmd_tokens);
820                 break;
821         case TEST_COMMAND_MARK_RELEASE_ALL:
822                 process_mark_for_release_all_cmd(cmd_tokens);
823                 break;
824         case TEST_COMMAND_MARK_RESIZE:
825                 process_resize_marked_cmd(cmd_tokens);
826                 break;
827         case TEST_COMMAND_COMMIT:
828                 process_commit_cmd(cmd_tokens);
829                 break;
830         case TEST_COMMAND_APP_CLASS_LIST:
831                 process_app_class_list_cmd(cmd_tokens);
832                 break;
833         case TEST_COMMAND_RES_TYPE_LIST:
834                 process_resource_type_list_cmd(cmd_tokens);
835                 break;
836         case TEST_COMMAND_RES_TYPE_COND_LIST:
837                 process_resource_type_condition_list_cmd(cmd_tokens);
838                 break;
839         case TEST_COMMAND_STATUS:
840                 process_status_cmd(cmd_tokens);
841                 break;
842         default:
843                 g_print("Invalid command\n");
844         }
845
846         g_string_free(cmd_line, TRUE);
847         g_strfreev(cmd_tokens);
848
849         display_menu();
850
851         return input(channel);
852 }
853
854 static void free_resource_manager(void *rm)
855 {
856         if (auto_destroy_manager)
857                 mm_resource_manager_destroy(rm);
858 }
859
860 static void free_resources(void *rs)
861 {
862         g_hash_table_destroy((GHashTable*)rs);
863 }
864
865 static gboolean check_const_string_arrays()
866 {
867         int i;
868
869         for (i = 0; resource_str[i]; i++);
870         if (i != MM_RESOURCE_MANAGER_RES_TYPE_MAX)
871                 return FALSE;
872
873         for (i = 0; app_class_str[i]; i++);
874         if (i != MM_RESOURCE_MANAGER_APP_CLASS_MAX)
875                 return FALSE;
876
877         for (i = 0; status_str[i]; i++);
878         if (i != MM_RESOURCE_MANAGER_STATUS_MAX)
879                 return FALSE;
880
881         for (i = 0; condition_str[i]; i++);
882         if (i != MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX)
883                 return FALSE;
884
885         return TRUE;
886 }
887
888 int main(int argc, char *argv[])
889 {
890         GIOChannel *stdin_channel;
891         int option;
892
893         if (!check_const_string_arrays()) {
894                 g_print("FATAL ERROR: Resource manager API was changed. The test suite must be changed too.\n");
895                 return 1;
896         }
897
898         while ((option = getopt(argc, argv, "?hs")) != -1) {
899                 switch (option) {
900                 case '?':
901                 case 'h':
902                         g_print("Usage: %s [-s]\n   s - don't display menu\n   ?,h - usage\n", argv[0]);
903                         return 0;
904                 case 's':
905                         skip_menu = TRUE;
906                         break;
907                 }
908         }
909
910         loop = g_main_loop_new(NULL, 0);
911         stdin_channel = g_io_channel_unix_new(fileno(stdin));
912         g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
913         g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc) input, NULL);
914
915         resource_managers = g_hash_table_new_full(NULL, NULL, free_resource_manager, free_resources);
916
917         display_menu();
918
919         g_main_loop_run(loop);
920         g_hash_table_destroy(resource_managers);
921         g_main_loop_unref(loop);
922
923         g_print("\n");
924
925         return 0;
926 }