1 #include "config.h"
2 
3 #include <stdlib.h>
4 #include <string.h>
5 #include <glib.h>
6 #include <gmodule.h>
7 
8 #include "backends/x11/nested/meta-backend-x11-nested.h"
9 #include "meta-test/meta-context-test.h"
10 #include "tests/clutter-test-utils.h"
11 
12 #include "test-unit-names.h"
13 
14 #define MAX_DESC_SIZE   72
15 
16 static GModule *module = NULL;
17 
18 static gpointer
get_symbol_with_suffix(const char * unit_name,const char * suffix)19 get_symbol_with_suffix (const char *unit_name,
20                         const char *suffix)
21 {
22   char *main_symbol_name;
23   gpointer func;
24 
25   main_symbol_name = g_strconcat (unit_name, "_", suffix, NULL);
26   main_symbol_name = g_strdelimit (main_symbol_name, "-", '_');
27 
28   g_module_symbol (module, main_symbol_name, &func);
29 
30   g_free (main_symbol_name);
31 
32   return func;
33 }
34 
35 static gpointer
get_unit_name_main(const char * unit_name)36 get_unit_name_main (const char *unit_name)
37 {
38   return get_symbol_with_suffix (unit_name, "main");
39 }
40 static char *
get_unit_name_description(const char * unit_name,gssize max_len)41 get_unit_name_description (const char *unit_name,
42                            gssize      max_len)
43 {
44   const char *description;
45   gpointer func;
46   char *retval;
47 
48   func = get_symbol_with_suffix (unit_name, "describe");
49   if (func == NULL)
50     description = "No description found";
51   else
52     {
53       const char *(* unit_test_describe) (void);
54 
55       unit_test_describe = func;
56 
57       description = unit_test_describe ();
58     }
59 
60   if (max_len > 0 && strlen (description) >= max_len)
61     {
62       GString *buf = g_string_sized_new (max_len);
63       char *newline;
64 
65       newline = strchr (description, '\n');
66       if (newline != NULL)
67         {
68           g_string_append_len (buf, description,
69                                MIN (newline - description - 1, max_len - 3));
70         }
71       else
72         g_string_append_len (buf, description, max_len - 3);
73 
74       g_string_append (buf, "...");
75 
76       retval = g_string_free (buf, FALSE);
77     }
78   else
79     retval = g_strdup (description);
80 
81   return retval;
82 }
83 
84 static gboolean list_all = FALSE;
85 static gboolean describe = FALSE;
86 static char **unit_names = NULL;
87 
88 static GOptionEntry entries[] = {
89   {
90     "describe", 'd',
91     0,
92     G_OPTION_ARG_NONE, &describe,
93     "Describe the interactive unit test", NULL,
94   },
95   {
96     "list-all", 'l',
97     0,
98     G_OPTION_ARG_NONE, &list_all,
99     "List all available units", NULL,
100   },
101   {
102     G_OPTION_REMAINING, 0,
103     0,
104     G_OPTION_ARG_STRING_ARRAY, &unit_names,
105     "The interactive unit test", "UNIT_NAME"
106   },
107   { NULL }
108 };
109 
110 int
main(int argc,char ** argv)111 main (int argc, char **argv)
112 {
113   int ret, i, n_unit_names;
114   GOptionContext *context;
115 
116   context = g_option_context_new (" - Interactive test suite");
117   g_option_context_add_main_entries (context, entries, NULL);
118   g_option_context_set_help_enabled (context, TRUE);
119   g_option_context_set_ignore_unknown_options (context, TRUE);
120   if (!g_option_context_parse (context, &argc, &argv, NULL))
121     {
122       g_print ("Usage: test-interactive <unit_test>\n");
123       return EXIT_FAILURE;
124     }
125 
126   g_option_context_free (context);
127 
128   module = g_module_open (NULL, 0);
129   if (!module)
130     g_error ("*** Failed to open self for symbol lookup");
131 
132   ret = EXIT_SUCCESS;
133 
134   if (list_all)
135     {
136       g_print ("* Available unit tests:\n");
137 
138       for (i = 0; i < G_N_ELEMENTS (test_unit_names); i++)
139         {
140           char *str;
141           gsize len;
142 
143           len = MAX_DESC_SIZE - strlen (test_unit_names[i]);
144           str = get_unit_name_description (test_unit_names[i], len - 2);
145 
146           g_print ("  - %s:%*s%s\n",
147                    test_unit_names[i],
148                    (int) (len - strlen (str)), " ",
149                    str);
150 
151           g_free (str);
152         }
153 
154       ret = EXIT_SUCCESS;
155       goto out;
156     }
157 
158   if (unit_names != NULL)
159     n_unit_names = g_strv_length (unit_names);
160   else
161     {
162       g_print ("Usage: test-interactive <unit_test>\n");
163       ret = EXIT_FAILURE;
164       goto out;
165     }
166 
167   for (i = 0; i < n_unit_names; i++)
168     {
169       const char *unit_name = unit_names[i];
170       char *unit_test = NULL;
171       gboolean found;
172       int j;
173 
174       unit_test = g_path_get_basename (unit_name);
175 
176       found = FALSE;
177       for (j = 0; j < G_N_ELEMENTS (test_unit_names); j++)
178         {
179           if (strcmp (test_unit_names[j], unit_test) == 0)
180             {
181               found = TRUE;
182               break;
183             }
184         }
185 
186       if (!found)
187         g_error ("*** Unit '%s' does not exist", unit_test);
188 
189       if (describe)
190         {
191           char *str;
192 
193           str = get_unit_name_description (unit_test, -1);
194 
195           g_print ("* %s:\n%s\n\n", unit_test, str);
196 
197           g_free (str);
198 
199           ret = EXIT_SUCCESS;
200         }
201       else
202         {
203           int (* unit_test_main) (int argc, char **argv);
204           gpointer func;
205 
206           func = get_unit_name_main (unit_test);
207           if (func == NULL)
208             g_error ("*** Unable to find the main entry point for '%s'", unit_test);
209 
210           unit_test_main = func;
211 
212           ret = unit_test_main (n_unit_names, unit_names);
213 
214           g_free (unit_test);
215 
216           break;
217         }
218 
219       g_free (unit_test);
220     }
221 
222 out:
223   g_module_close (module);
224 
225   return ret;
226 }
227 
228