1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <getopt.h>
8 #include <unistd.h>
9 
10 #include <Eina.h>
11 #include <Eet.h>
12 #include <Ecore.h>
13 #include <Ecore_Getopt.h>
14 #include <Elementary.h>
15 
16 #include "common.h"
17 
18 #define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
19 #define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
20 
21 static int _log_domain = -1;
22 
23 static Eina_Stringshare *_src_filename = NULL;
24 static Exactness_Unit *_src_unit = NULL;
25 static int _verbose = 0;
26 
27 static Eina_Debug_Session *_session = NULL;
28 static int _cid = -1, _pid = -1;
29 static Eina_List *_cur_event_list = NULL;
30 
31 static int _all_apps_get_op = EINA_DEBUG_OPCODE_INVALID;
32 static int _mouse_in_op = EINA_DEBUG_OPCODE_INVALID;
33 static int _mouse_out_op = EINA_DEBUG_OPCODE_INVALID;
34 static int _mouse_wheel_op = EINA_DEBUG_OPCODE_INVALID;
35 static int _multi_down_op = EINA_DEBUG_OPCODE_INVALID;
36 static int _multi_up_op = EINA_DEBUG_OPCODE_INVALID;
37 static int _multi_move_op = EINA_DEBUG_OPCODE_INVALID;
38 static int _key_down_op = EINA_DEBUG_OPCODE_INVALID;
39 static int _key_up_op = EINA_DEBUG_OPCODE_INVALID;
40 static int _take_shot_op = EINA_DEBUG_OPCODE_INVALID;
41 static int _efl_event_op = EINA_DEBUG_OPCODE_INVALID;
42 static int _click_on_op = EINA_DEBUG_OPCODE_INVALID;
43 static int _stabilize_op = EINA_DEBUG_OPCODE_INVALID;
44 static int _finish_op = EINA_DEBUG_OPCODE_INVALID;
45 
46 static Eina_Bool _all_apps_get_cb(Eina_Debug_Session *, int , void *, int);
47 
48 EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
49       {"Daemon/Client/register_observer", &_all_apps_get_op, NULL},
50       {"Daemon/Client/added", NULL, &_all_apps_get_cb},
51       {"Exactness/Actions/Mouse In", &_mouse_in_op, NULL},
52       {"Exactness/Actions/Mouse Out", &_mouse_out_op, NULL},
53       {"Exactness/Actions/Mouse Wheel", &_mouse_wheel_op, NULL},
54       {"Exactness/Actions/Multi Down", &_multi_down_op, NULL},
55       {"Exactness/Actions/Multi Up", &_multi_up_op, NULL},
56       {"Exactness/Actions/Multi Move", &_multi_move_op, NULL},
57       {"Exactness/Actions/Key Down", &_key_down_op, NULL},
58       {"Exactness/Actions/Key Up", &_key_up_op, NULL},
59       {"Exactness/Actions/Take Shot", &_take_shot_op, NULL},
60       {"Exactness/Actions/EFL Event", &_efl_event_op, NULL},
61       {"Exactness/Actions/Click On", &_click_on_op, NULL},
62       {"Exactness/Actions/Stabilize", &_stabilize_op, NULL},
63       {"Exactness/Actions/Finish", &_finish_op, NULL},
64       {NULL, NULL, NULL}
65       );
66 
67 static void
_feed_event(Exactness_Action_Type type,unsigned int n_evas,void * data)68 _feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data)
69 {
70    switch (type)
71      {
72       case EXACTNESS_ACTION_MOUSE_IN:
73            {
74               INF("Mouse in\n");
75               DBG("%s evas_event_feed_mouse_in n_evas=<%d>\n", __func__, n_evas);
76               eina_debug_session_send(_session, _cid, _mouse_in_op, &n_evas, sizeof(int));
77               break;
78            }
79       case EXACTNESS_ACTION_MOUSE_OUT:
80            {
81               INF("Mouse out\n");
82               DBG("%s evas_event_feed_mouse_out n_evas=<%d>\n", __func__, n_evas);
83               eina_debug_session_send(_session, _cid, _mouse_out_op, &n_evas, sizeof(int));
84               break;
85            }
86       case EXACTNESS_ACTION_MOUSE_WHEEL:
87            {
88               Exactness_Action_Mouse_Wheel *t = data;
89               int len = 3*sizeof(int);
90               char *buf = malloc(len), *tmp = buf;
91               INF("Mouse wheel\n");
92               DBG("%s evas_event_feed_mouse_wheel n_evas=<%d>\n", __func__, n_evas);
93               STORE_INT(tmp, n_evas);
94               STORE_INT(tmp, t->direction);
95               STORE_INT(tmp, t->z);
96               eina_debug_session_send(_session, _cid, _mouse_wheel_op, buf, len);
97               free(buf);
98               break;
99            }
100       case EXACTNESS_ACTION_MULTI_DOWN:
101       case EXACTNESS_ACTION_MULTI_UP:
102            {
103               Exactness_Action_Multi_Event *t = data;
104               int len = 5*sizeof(int)+7*sizeof(double)+sizeof(int);
105               char *buf = malloc(len), *tmp = buf;
106               DBG("%s %s n_evas=<%d>\n", __func__,
107                     type == EXACTNESS_ACTION_MULTI_DOWN ? "evas_event_feed_multi_down" :
108                     "evas_event_feed_multi_up", n_evas);
109               STORE_INT(tmp, n_evas);
110               STORE_INT(tmp, t->d);
111               STORE_INT(tmp, t->b);
112               STORE_INT(tmp, t->x);
113               STORE_INT(tmp, t->y);
114               STORE_DOUBLE(tmp, t->rad);
115               STORE_DOUBLE(tmp, t->radx);
116               STORE_DOUBLE(tmp, t->rady);
117               STORE_DOUBLE(tmp, t->pres);
118               STORE_DOUBLE(tmp, t->ang);
119               STORE_DOUBLE(tmp, t->fx);
120               STORE_DOUBLE(tmp, t->fy);
121               STORE_INT(tmp, t->flags);
122               eina_debug_session_send(_session, _cid,
123                     type == EXACTNESS_ACTION_MULTI_DOWN ? _multi_down_op : _multi_up_op,
124                     buf, len);
125               free(buf);
126               break;
127            }
128       case EXACTNESS_ACTION_MULTI_MOVE:
129            {
130               Exactness_Action_Multi_Move *t = data;
131               int len = 4*sizeof(int)+7*sizeof(double);
132               char *buf = malloc(len), *tmp = buf;
133               DBG("%s evas_event_feed_multi_move n_evas=<%d>\n", __func__, n_evas);
134               STORE_INT(tmp, n_evas);
135               STORE_INT(tmp, t->d);
136               STORE_INT(tmp, t->x);
137               STORE_INT(tmp, t->y);
138               STORE_DOUBLE(tmp, t->rad);
139               STORE_DOUBLE(tmp, t->radx);
140               STORE_DOUBLE(tmp, t->rady);
141               STORE_DOUBLE(tmp, t->pres);
142               STORE_DOUBLE(tmp, t->ang);
143               STORE_DOUBLE(tmp, t->fx);
144               STORE_DOUBLE(tmp, t->fy);
145               eina_debug_session_send(_session, _cid, _multi_move_op, buf, len);
146               free(buf);
147               break;
148            }
149       case EXACTNESS_ACTION_KEY_DOWN:
150       case EXACTNESS_ACTION_KEY_UP:
151            {
152               Exactness_Action_Key_Down_Up *t = data;
153               int len = 2*sizeof(int) + 4 + 1;
154               len += t->keyname ? strlen(t->keyname) : 0;
155               len += t->key ? strlen(t->key) : 0;
156               len += t->string ? strlen(t->string) : 0;
157               len += t->compose ? strlen(t->compose) : 0;
158               char *buf = malloc(len), *tmp = buf;
159               DBG("%s %s n_evas=<%d>\n", __func__,
160                     type == EXACTNESS_ACTION_KEY_DOWN ? "evas_event_feed_key_down " :
161                     "evas_event_feed_key_up", n_evas);
162               STORE_INT(tmp, n_evas);
163               STORE_STRING(tmp, t->keyname);
164               STORE_STRING(tmp, t->key);
165               STORE_STRING(tmp, t->string);
166               STORE_STRING(tmp, t->compose);
167               STORE_INT(tmp, t->keycode);
168               eina_debug_session_send(_session, _cid,
169                     type == EXACTNESS_ACTION_KEY_DOWN ? _key_down_op : _key_up_op,
170                     buf, len);
171               free(buf);
172               break;
173            }
174       case EXACTNESS_ACTION_TAKE_SHOT:
175            {
176               DBG("%s take shot n_evas=<%d>\n", __func__, n_evas);
177               eina_debug_session_send(_session, _cid, _take_shot_op, &n_evas, sizeof(int));
178               break;
179            }
180       case EXACTNESS_ACTION_EFL_EVENT:
181            {
182               Exactness_Action_Efl_Event *t = data;
183               int len = 2;
184               len += t->wdg_name ? strlen(t->wdg_name) : 0;
185               len += t->event_name ? strlen(t->event_name) : 0;
186               char *buf = malloc(len), *tmp = buf;
187               DBG("%s %s\n", __func__, "EFL event");
188               STORE_STRING(tmp, t->wdg_name);
189               STORE_STRING(tmp, t->event_name);
190               eina_debug_session_send(_session, _cid, _efl_event_op, buf, len);
191               free(buf);
192               break;
193            }
194       case EXACTNESS_ACTION_CLICK_ON:
195            {
196               Exactness_Action_Click_On *t = data;
197               int len = 1;
198               len += t->wdg_name ? strlen(t->wdg_name) : 0;
199               char *buf = malloc(len), *tmp = buf;
200               DBG("%s %s\n", __func__, "Click On");
201               STORE_STRING(tmp, t->wdg_name);
202               eina_debug_session_send(_session, _cid, _click_on_op, buf, len);
203               free(buf);
204               break;
205            }
206       case EXACTNESS_ACTION_STABILIZE:
207            {
208               DBG("%s stabilize\n", __func__);
209               eina_debug_session_send(_session, _cid, _stabilize_op, NULL, 0);
210               break;
211            }
212       default: /* All non-input events are not handeled */
213          break;
214      }
215 }
216 
217 static Eina_Bool
_feed_event_timer_cb(void * data EINA_UNUSED)218 _feed_event_timer_cb(void *data EINA_UNUSED)
219 {
220    Exactness_Action *act = eina_list_data_get(_cur_event_list);
221    _feed_event(act->type, act->n_evas, act->data);
222 
223    _cur_event_list = eina_list_next(_cur_event_list);
224 
225    if (!_cur_event_list)
226      {  /* Finished reading all events */
227         eina_debug_session_send(_session, _cid, _finish_op, NULL, 0);
228         ecore_main_loop_quit();
229      }
230    else
231      {
232         Exactness_Action *cur_act = eina_list_data_get(_cur_event_list);
233         ecore_timer_add(cur_act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
234      }
235    return ECORE_CALLBACK_CANCEL;
236 }
237 
238 static Eina_Bool
_src_open()239 _src_open()
240 {
241    double diff_time = 0; /* Time to wait before feeding the first event */
242 
243    DBG("<%s> Source file is <%s>\n", __func__, _src_filename);
244    if (!strcmp(_src_filename + strlen(_src_filename) - 4,".exu"))
245      {
246         _src_unit = exactness_unit_file_read(_src_filename);
247      }
248    if (!_src_unit) return EINA_FALSE;
249    _cur_event_list = _src_unit->actions;
250    Exactness_Action *act = eina_list_data_get(_cur_event_list);
251 
252    if (act->delay_ms)
253      {
254         DBG("  Waiting <%f>\n", diff_time);
255         ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
256      }
257    else
258      {
259         _feed_event_timer_cb(NULL);
260      }
261    return EINA_TRUE;
262 }
263 
264 static void
_main_loop_all_apps_get_cb(Eina_Debug_Session * session EINA_UNUSED,int srcid EINA_UNUSED,void * buffer,int size EINA_UNUSED)265 _main_loop_all_apps_get_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
266 {
267    char *buf = buffer;
268    int chosen_cid = -1;
269    if (_cid != -1) return;
270    while (size > 0)
271      {
272         int cid, pid, len;
273         cid = EXTRACT_INT(buf);
274         pid = EXTRACT_INT(buf);
275         if (_pid != -1)
276           {
277              if (_pid == pid)
278                {
279                   _cid = cid;
280                   _src_open();
281                   return;
282                }
283           }
284         else
285           {
286              if (!strcmp(buf, "exactness_play"))
287                {
288                   if (chosen_cid != -1)
289                     {
290                        fprintf(stderr, "Need to specify a PID - too much choice\n");
291                        return;
292                     }
293                   chosen_cid = cid;
294                }
295           }
296         len = strlen(buf) + 1;
297         buf += len;
298         size -= (2 * sizeof(int) + len);
299      }
300    if (chosen_cid != -1)
301      {
302         _cid = chosen_cid;
303         _src_open();
304      }
305 }
306 
WRAPPER_TO_XFER_MAIN_LOOP(_all_apps_get_cb)307 WRAPPER_TO_XFER_MAIN_LOOP(_all_apps_get_cb)
308 
309 static void
310 _ops_ready_cb(void *data EINA_UNUSED, Eina_Bool status)
311 {
312    if (status)
313       eina_debug_session_send(_session, 0, _all_apps_get_op, NULL, 0);
314 }
315 
316 static const Ecore_Getopt optdesc = {
317   "exactness_inject",
318   "%prog [options] <-v|-p|-t|-h> command",
319   PACKAGE_VERSION,
320   "(C) 2018 Enlightenment",
321   "BSD",
322   "A scenario events injector for EFL based applications.",
323   1,
324   {
325     ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
326     ECORE_GETOPT_STORE_INT('p', "pid", "PID of the application to connect to"),
327     ECORE_GETOPT_STORE_INT('r', "remote-port", "Port to connect remotely to the daemon. Local connection if not specified"),
328     ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
329 
330     ECORE_GETOPT_LICENSE('L', "license"),
331     ECORE_GETOPT_COPYRIGHT('C', "copyright"),
332     ECORE_GETOPT_VERSION('V', "version"),
333     ECORE_GETOPT_HELP('h', "help"),
334     ECORE_GETOPT_SENTINEL
335   }
336 };
337 
main(int argc,char ** argv)338 int main(int argc, char **argv)
339 {
340    int opt_args = 0, real__ = 1, port = -1;
341    char *src = NULL;
342    Eina_Value *ret__;
343    Eina_Bool want_quit = EINA_FALSE;
344 
345    Ecore_Getopt_Value values[] = {
346      ECORE_GETOPT_VALUE_STR(src),
347      ECORE_GETOPT_VALUE_INT(_pid),
348      ECORE_GETOPT_VALUE_INT(port),
349      ECORE_GETOPT_VALUE_INT(_verbose),
350 
351      ECORE_GETOPT_VALUE_BOOL(want_quit),
352      ECORE_GETOPT_VALUE_BOOL(want_quit),
353      ECORE_GETOPT_VALUE_BOOL(want_quit),
354      ECORE_GETOPT_VALUE_BOOL(want_quit),
355      ECORE_GETOPT_VALUE_NONE
356    };
357 
358    _log_domain = eina_log_domain_register("exactness_injector", NULL);
359 
360    if (!ecore_evas_init())
361       return EXIT_FAILURE;
362 
363    opt_args = ecore_getopt_parse(&optdesc, values, argc, argv);
364    if (opt_args < 0)
365      {
366         fprintf(stderr, "Failed parsing arguments.\n");
367         goto end;
368      }
369    if (want_quit) goto end;
370 
371    if (!src)
372      {
373         fprintf(stderr, "no test file specified\n");
374         goto end;
375      }
376    _src_filename = eina_stringshare_add(src);
377 
378    if (port == -1)
379       _session = eina_debug_local_connect(EINA_TRUE);
380    else
381       _session = eina_debug_remote_connect(port);
382    eina_debug_opcodes_register(_session, _debug_ops(), _ops_ready_cb, NULL);
383 
384    elm_init(argc, argv);
385    ret__ = efl_loop_begin(efl_main_loop_get());
386    real__ = efl_loop_exit_code_process(ret__);
387    elm_shutdown();
388 end:
389    ecore_evas_shutdown();
390    eina_log_domain_unregister(_log_domain);
391    _log_domain = -1;
392    return real__;
393 }
394