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