jackdanielz pushed a commit to branch master.

http://git.enlightenment.org/tools/exactness.git/commit/?id=dd4c1caade9e27af1f6622a2a4f047514ec5f819

commit dd4c1caade9e27af1f6622a2a4f047514ec5f819
Author: Daniel Zaoui <[email protected]>
Date:   Thu Oct 13 07:46:39 2016 +0300

    Store and compare objects information at every shot
    
    This feature is aimed to provide a new way to debug applications during
    scenarios playing.
    When a difference happens between two shots of an application, the
    investigation can be tough as the cause may be hidden into a tiny
    change, such as an update of the theme.
    This feature tries to respond to this problem by storing objects of
    the application every time a shot is taken. Then during shots comparison,
    objects information are compared and differences are displayed on the
    screen.
    
    The feature can be used with the -S option.
    
    For the moment, only hierarchy, order and geometry are checked.
---
 src/bin/Makefile.am          |   2 +-
 src/bin/exactness.c          |   2 +
 src/bin/exactness_config.h   |   1 +
 src/bin/exactness_helper.c   |  66 +++++++++++++++---
 src/bin/run_test.c           |  47 +++++++++----
 src/lib/tsuite_file_data.c   | 108 +++++++++++++++++++++++++++++
 src/lib/tsuite_file_data.h   |  22 ++++++
 src/lib/tsuite_hook_player.c | 161 ++++++++++++++++++++++++++++++++++++++++++-
 8 files changed, 383 insertions(+), 26 deletions(-)

diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 3998cc8..46b0993 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -12,7 +12,7 @@ exactness_SOURCES = \
 exactness_helper_SOURCES = exactness_helper.c
 
 exactness_LDADD = \
-                   @EFL_LIBS@
+                   @EFL_LIBS@ ../lib/libexactness_player.la
 
 exactness_helper_LDADD = \
                    @EFL_LIBS@ ../lib/libexactness_player.la
diff --git a/src/bin/exactness.c b/src/bin/exactness.c
index 2e60eab..5c82a7a 100644
--- a/src/bin/exactness.c
+++ b/src/bin/exactness.c
@@ -40,6 +40,7 @@ static const Ecore_Getopt optdesc = {
     ECORE_GETOPT_STORE_TRUE('p', "play", "Run in play mode."),
     ECORE_GETOPT_STORE_TRUE('i', "init", "Run in init mode."),
     ECORE_GETOPT_STORE_TRUE('s', "simulation", "Run in simulation mode."),
+    ECORE_GETOPT_STORE_TRUE('S', "store-objects", "Store information about 
objects at every screen shot time."),
     ECORE_GETOPT_STORE_TRUE('v', "verbose", "Turn verbose messages on."),
 
     ECORE_GETOPT_LICENSE('L', "license"),
@@ -69,6 +70,7 @@ main(int argc, char *argv[])
      ECORE_GETOPT_VALUE_BOOL(mode_play),
      ECORE_GETOPT_VALUE_BOOL(mode_init),
      ECORE_GETOPT_VALUE_BOOL(mode_simulation),
+     ECORE_GETOPT_VALUE_BOOL(exactness_config.store_objects),
      ECORE_GETOPT_VALUE_BOOL(exactness_config.verbose),
 
      ECORE_GETOPT_VALUE_BOOL(want_quit),
diff --git a/src/bin/exactness_config.h b/src/bin/exactness_config.h
index e207c51..60d902e 100644
--- a/src/bin/exactness_config.h
+++ b/src/bin/exactness_config.h
@@ -12,6 +12,7 @@ struct _Exactness_Config
    char *dest_dir;
    char *wrap_command;
    Eina_Bool verbose;
+   Eina_Bool store_objects;
 };
 
 extern Exactness_Config exactness_config;
diff --git a/src/bin/exactness_helper.c b/src/bin/exactness_helper.c
index 12945b2..0cf4b21 100644
--- a/src/bin/exactness_helper.c
+++ b/src/bin/exactness_helper.c
@@ -116,7 +116,7 @@ _event_specific_info_get(const Variant_st *v, char 
output[1024])
 }
 static const Ecore_Getopt optdesc = {
   "exactness_helper",
-  "%prog [options] <rec file>",
+  "%prog [options] [<rec file> | <file1 file2>]",
   NULL,
   "(C) 2016 Enlightenment",
   "BSD",
@@ -125,7 +125,8 @@ static const Ecore_Getopt optdesc = {
   {
     ECORE_GETOPT_STORE_USHORT('d', "delay", "Delay the given recording by a 
given time (in seconds)."),
     ECORE_GETOPT_STORE_TRUE('c', "clean", "Clean the given recording from 
wrong events."),
-    ECORE_GETOPT_STORE_TRUE('l', "list", "List the events of the given 
recording"),
+    ECORE_GETOPT_STORE_TRUE('l', "list", "List the events of the given 
recording."),
+    ECORE_GETOPT_STORE_TRUE('C', "compare", "Compare two given files (images 
files or objects eet files)."),
 
     ECORE_GETOPT_LICENSE('L', "license"),
     ECORE_GETOPT_COPYRIGHT('C', "copyright"),
@@ -149,14 +150,15 @@ _is_hook_duplicate(const Variant_st *cur_v, const 
Variant_st *prev_v)
 int
 main(int argc, char *argv[])
 {
-   const char *rec_file = NULL;
+   const char *rec_file = NULL, *comp1 = NULL, *comp2 = NULL;
    int ret = 0, args = 0;
    unsigned short delay = 0;
-   Eina_Bool want_quit, clean = EINA_FALSE, list_get = EINA_FALSE;
+   Eina_Bool want_quit, clean = EINA_FALSE, list_get = EINA_FALSE, 
compare_files = EINA_FALSE;
    Ecore_Getopt_Value values[] = {
      ECORE_GETOPT_VALUE_USHORT(delay),
      ECORE_GETOPT_VALUE_BOOL(clean),
      ECORE_GETOPT_VALUE_BOOL(list_get),
+     ECORE_GETOPT_VALUE_BOOL(compare_files),
 
      ECORE_GETOPT_VALUE_BOOL(want_quit),
      ECORE_GETOPT_VALUE_BOOL(want_quit),
@@ -180,17 +182,33 @@ main(int argc, char *argv[])
         ret = 1;
         goto end;
      }
-   else if (args == argc)
+   else if ((clean || delay || list_get) && args == argc)
      {
         fprintf(stderr, "Expected rec file as the last argument..\n");
         ecore_getopt_help(stderr, &optdesc);
         ret = 1;
         goto end;
      }
+   else if (compare_files && argc - args != 2)
+     {
+        fprintf(stderr, "Expected two files to compare as last arguments..\n");
+        ecore_getopt_help(stderr, &optdesc);
+        ret = 1;
+        goto end;
+     }
 
-   rec_file = argv[args];
-   Timer_Data td;
-   Lists_st *list = read_events(rec_file, &td);
+   Lists_st *list = NULL;
+   if (clean || delay || list_get)
+     {
+        rec_file = argv[args];
+        Timer_Data td;
+        list = read_events(rec_file, &td);
+     }
+   if (compare_files)
+     {
+        comp1 = argv[args];
+        comp2 = argv[args+1];
+     }
 
    if (clean)
      {
@@ -243,7 +261,37 @@ main(int argc, char *argv[])
           }
      }
 
-   write_events(rec_file, list);
+   if (compare_files)
+     {
+        const char *ext = strrchr(comp1, '.');
+        if (!ext)
+          {
+             fprintf(stderr, "Extension required\n");
+             goto end;
+          }
+        if (!strcmp(ext, ".eet"))
+          {
+             if (!objects_files_compare(comp1, comp2, EINA_TRUE))
+               {
+                  fprintf(stderr, "Failed objects comparing\n");
+               }
+          }
+        else
+          {
+             char buf[1024];
+
+             /* FIXME: Clean up. */
+             snprintf(buf, sizeof(buf),
+                   "compare '%s' '%s' 'comp_file%s'",
+                   comp1, comp2, ext);
+             if (system(buf))
+               {
+                  fprintf(stderr, "Failed image comparing '%s' and '%s'\n", 
comp1, comp2);
+               }
+          }
+     }
+
+   if (rec_file) write_events(rec_file, list);
 
 end:
    ecore_shutdown();
diff --git a/src/bin/run_test.c b/src/bin/run_test.c
index 6e4f1d6..27365ef 100644
--- a/src/bin/run_test.c
+++ b/src/bin/run_test.c
@@ -9,6 +9,8 @@
 #include "exactness_config.h"
 #include "exactness_private.h"
 
+#include "tsuite_file_data.h"
+
 #define CONFIG "ELM_SCALE=1 ELM_FINGER_SIZE=10"
 
 typedef enum
@@ -38,6 +40,8 @@ _run_command_prepare(const List_Entry *ent, Run_Mode mode, 
char *buf)
               eina_strbuf_append(sbuf, "ELM_ENGINE='buffer' ");
               eina_strbuf_append_printf(sbuf, "TSUITE_DEST_DIR='%s/%s' ",
                     exactness_config.dest_dir, CURRENT_SUBDIR);
+              if (exactness_config.store_objects)
+                 eina_strbuf_append(sbuf, "TSUITE_STORE_OBJECTS=1 ");
               break;
            }
       case RUN_INIT:
@@ -45,6 +49,8 @@ _run_command_prepare(const List_Entry *ent, Run_Mode mode, 
char *buf)
               eina_strbuf_append(sbuf, "ELM_ENGINE='buffer' ");
               eina_strbuf_append_printf(sbuf, "TSUITE_DEST_DIR='%s/%s' ",
                     exactness_config.dest_dir, ORIG_SUBDIR);
+              if (exactness_config.store_objects)
+                 eina_strbuf_append(sbuf, "TSUITE_STORE_OBJECTS=1 ");
               break;
            }
       case RUN_RECORD:
@@ -159,24 +165,35 @@ _compare_list_cb(const char *name, const char *path 
EINA_UNUSED, void *data)
    if (_check_prefix(prefix, name))
      {
         char filename1[EXACTNESS_PATH_MAX], filename2[EXACTNESS_PATH_MAX];
-        snprintf(filename1, EXACTNESS_PATH_MAX, "%s/%s/%s", 
exactness_config.dest_dir, CURRENT_SUBDIR, name);
-        snprintf(filename2, EXACTNESS_PATH_MAX, "%s/%s/%s", 
exactness_config.dest_dir, ORIG_SUBDIR, name);
+        snprintf(filename1, EXACTNESS_PATH_MAX, "%s/%s/%s", 
exactness_config.dest_dir, ORIG_SUBDIR, name);
+        snprintf(filename2, EXACTNESS_PATH_MAX, "%s/%s/%s", 
exactness_config.dest_dir, CURRENT_SUBDIR, name);
         if (!_is_equal(filename1, filename2))
           {
-             char buf[EXACTNESS_PATH_MAX];
-             exactness_ctx.compare_errors =
-                eina_list_append(exactness_ctx.compare_errors,
-                      strdup(name));
-
-             /* FIXME: Clean up. */
-             snprintf(buf, EXACTNESS_PATH_MAX,
-                   "compare '%s' '%s' '%s/%s/comp_%s'",
-                   filename1, filename2,
-                   exactness_config.dest_dir,
-                   CURRENT_SUBDIR, name);
-             if (system(buf))
+             const char *ext = strrchr(name, '.');
+             if (!strcmp(ext, ".eet"))
+               {
+                  if (!objects_files_compare(filename1, filename2, EINA_FALSE))
+                    {
+                       fprintf(stderr, "Failed objects comparing '%s'\n", 
name);
+                    }
+               }
+             else
                {
-                  fprintf(stderr, "Failed image comparing '%s'\n", name);
+                  char buf[EXACTNESS_PATH_MAX];
+                  exactness_ctx.compare_errors =
+                     eina_list_append(exactness_ctx.compare_errors,
+                           strdup(name));
+
+                  /* FIXME: Clean up. */
+                  snprintf(buf, EXACTNESS_PATH_MAX,
+                        "compare '%s' '%s' '%s/%s/comp_%s'",
+                        filename1, filename2,
+                        exactness_config.dest_dir,
+                        CURRENT_SUBDIR, name);
+                  if (system(buf))
+                    {
+                       fprintf(stderr, "Failed image comparing '%s'\n", name);
+                    }
                }
           }
      }
diff --git a/src/lib/tsuite_file_data.c b/src/lib/tsuite_file_data.c
index a0e6104..a71362b 100644
--- a/src/lib/tsuite_file_data.c
+++ b/src/lib/tsuite_file_data.c
@@ -728,6 +728,114 @@ multi_move_desc_make(void)
    return _d;
 }
 
+Eet_Data_Descriptor *
+object_info_desc_make(void)
+{
+   Eet_Data_Descriptor_Class eddc;
+   static Eet_Data_Descriptor *info_d = NULL;
+   if (!info_d)
+     {
+        EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Object_Info);
+        info_d = eet_data_descriptor_stream_new(&eddc);
+        EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "kl_name", kl_name, 
EET_T_STRING);
+        EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "id", id, 
EET_T_UINT);
+        EET_DATA_DESCRIPTOR_ADD_LIST(info_d, Object_Info, "children", 
children, info_d);
+        /* Evas stuff */
+        EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "x", x, EET_T_INT);
+        EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "y", y, EET_T_INT);
+        EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "w", w, EET_T_INT);
+        EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "h", h, EET_T_INT);
+     }
+
+   return info_d;
+}
+
+#define INFO_CHECK(i1, i2, obj_path, var) \
+   ({ \
+   Eina_Bool _ret = EINA_TRUE; \
+   if (i1->var != i2->var) \
+   { \
+      if (verbose) fprintf(stderr, "%s value is different for %s: %d-%d\n", 
#var, obj_path, i1->var, i2->var); \
+      _ret = EINA_FALSE; \
+   } \
+   _ret; \
+    })
+
+
+static Eina_Bool
+_object_info_compare(Object_Info *info1, Object_Info *info2, Eina_Bool 
verbose, const char *path)
+{
+   /* The caller has to give 2 infos whose kl_name and id are respectively the 
same */
+   Eina_List *itr1, *itr2;
+   Object_Info *c1, *c2;
+   int cnt1, cnt2;
+   Eina_Bool ret = EINA_TRUE;
+   char fpath[512];
+   if (!info1 || !info2) return EINA_FALSE;
+   if (info1->kl_name)
+      sprintf(fpath, "%s/%s_%d", path, info1->kl_name, info1->id);
+   else
+      *fpath = '\0';
+
+   ret &= INFO_CHECK(info1, info2, fpath, x);
+   ret &= INFO_CHECK(info1, info2, fpath, y);
+   ret &= INFO_CHECK(info1, info2, fpath, w);
+   ret &= INFO_CHECK(info1, info2, fpath, h);
+
+   cnt1 = eina_list_count(info1->children);
+   cnt2 = eina_list_count(info2->children);
+   if (cnt1 != cnt2 && verbose)
+      fprintf(stderr, "Object %s - number of children differs (%d - %d)\n", 
fpath, cnt1, cnt2);
+   EINA_LIST_FOREACH(info1->children, itr1, c1)
+     {
+        Eina_Bool found = EINA_FALSE;
+        if (!verbose && !ret) goto end;
+        EINA_LIST_FOREACH(info2->children, itr2, c2)
+          {
+             if (!found && c1->id == c2->id && c1->kl_name == c2->kl_name)
+               {
+                  found = EINA_TRUE;
+                  ret &= _object_info_compare(c1, c2, verbose, fpath);
+               }
+          }
+    }
+end:
+   return ret;
+}
+
+EAPI Eina_Bool
+objects_files_compare(const char *filename1, const char *filename2, Eina_Bool 
verbose)
+{
+   Eina_Bool ret = EINA_FALSE;
+   Eet_File *f1, *f2;
+   Eet_Data_Descriptor *desc = NULL;
+   Object_Info *lst1 = NULL, *lst2 = NULL;
+
+   f1 = eet_open(filename1, EET_FILE_MODE_READ);
+   f2 = eet_open(filename2, EET_FILE_MODE_READ);
+   desc = object_info_desc_make();
+   if (!f1 || !f2)
+     {
+        if (verbose) fprintf(stderr, "Can't open %s\n", 
!f1?filename1:filename2);
+        goto end;
+     }
+
+   lst1 = eet_data_read(f1, desc, "entry");
+   lst2 = eet_data_read(f2, desc, "entry");
+   if (!lst1 || !lst2)
+     {
+        if (verbose) fprintf(stderr, "Can't decode %s data\n", 
!lst1?filename1:filename2);
+        goto end;
+     }
+
+   ret = _object_info_compare(lst1, lst2, verbose, NULL);
+end:
+   if (desc) eet_data_descriptor_free(desc);
+   if (f1) eet_close(f1);
+   if (f2) eet_close(f2);
+   return ret;
+}
+
 /* declaring types */
 data_desc *_data_descriptors_init(void)
 {
diff --git a/src/lib/tsuite_file_data.h b/src/lib/tsuite_file_data.h
index 73c341c..831828d 100644
--- a/src/lib/tsuite_file_data.h
+++ b/src/lib/tsuite_file_data.h
@@ -245,6 +245,28 @@ data_desc *_data_descriptors_init(void);
 void _data_descriptors_shutdown(void);
 /* END   Event struct descriptors */
 
+/* START Objects */
+typedef struct
+{
+   Eo *object;
+   Eo *parent;
+   const char *kl_name;
+   Eina_List *children;
+   int id;
+
+   /* Evas stuff */
+   int x;
+   int y;
+   int w;
+   int h;
+} Object_Info;
+
+Eet_Data_Descriptor *object_info_desc_make(void);
+
+EAPI Eina_Bool objects_files_compare(const char *filename1, const char 
*filename2, Eina_Bool verbose);
+/* END Objects */
+
+
 Tsuite_Event_Type tsuite_event_mapping_type_get(const char *name);
 const char * tsuite_event_mapping_type_str_get(Tsuite_Event_Type t);
 const char * _variant_type_get(const void *data, Eina_Bool *unknow);
diff --git a/src/lib/tsuite_hook_player.c b/src/lib/tsuite_hook_player.c
index e5dcc92..9c0230c 100644
--- a/src/lib/tsuite_hook_player.c
+++ b/src/lib/tsuite_hook_player.c
@@ -18,6 +18,7 @@
 
 #define TSUITE_MAX_PATH 1024
 #define IMAGE_FILENAME_EXT ".png"
+#define OBJECTS_FILENAME_EXT ".eet"
 
 struct _evas_hook_setting
 {
@@ -25,6 +26,7 @@ struct _evas_hook_setting
    char *test_name;
    char *file_name;
    Eina_Bool verbose;
+   Eina_Bool store_objects;
 };
 typedef struct _evas_hook_setting evas_hook_setting;
 
@@ -34,6 +36,15 @@ static Tsuite_Data ts;
 static Eina_List *evas_list = NULL; /* List of Evas pointers */
 static int ignore_evas_new = 0; /* Counter to know if we should ignore evas 
new or not. */
 
+typedef struct
+{
+   const char *kl_name;
+   int last;
+} Main_Widget_Id;
+static Eina_List *_main_widget_ids = NULL;
+static Object_Info _widgets_list = {0};
+static void _objects_snapshot_do();
+
 static void
 _tsuite_verbosef(const char *fmt, ...)
 {
@@ -85,7 +96,6 @@ _shot_do(char *name, Evas *e)
         filename = malloc(strlen(_hook_setting->test_name) + 
strlen(IMAGE_FILENAME_EXT) +
               dir_name_len + 8); /* also space for serial */
 
-        ts.serial++;
         if (_hook_setting->dest_dir)
           sprintf(filename, "%s/", _hook_setting->dest_dir);
 
@@ -142,6 +152,7 @@ ecore_init(void)
         _hook_setting->dest_dir = getenv("TSUITE_DEST_DIR");
         _hook_setting->test_name = getenv("TSUITE_TEST_NAME");
         _hook_setting->file_name = getenv("TSUITE_FILE_NAME");
+        _hook_setting->store_objects = !!getenv("TSUITE_STORE_OBJECTS");
         tmp = getenv("TSUITE_VERBOSE");
         if (tmp)
            _hook_setting->verbose = atoi(tmp);
@@ -459,10 +470,12 @@ tsuite_feed_event(void *data)
               printf("%s take shot  timestamp=<%u> t->n_evas=<%d>\n", 
__func__, t->timestamp, t->n_evas);
 #endif
               if (rect) evas_object_color_set(rect, 0, 0, 255, 255);
+              ts.serial++;
               if (_hook_setting->dest_dir)
                 {
                    _shot_do(NULL,
                          eina_list_nth(evas_list, t->n_evas)); /* Serial name 
based on test-name */
+                   if (_hook_setting->store_objects) _objects_snapshot_do();
                 }
               break;
            }
@@ -547,3 +560,149 @@ ecore_main_loop_begin(void)
 
    return _ecore_main_loop_begin();
 }
+
+static void
+_obj_del(void *data EINA_UNUSED, const Efl_Event *event)
+{
+   Eo *parent = efl_parent_get(event->object);
+   Object_Info *info = efl_key_data_get(event->object, "exactness_info");
+   if (parent)
+     {
+        Object_Info *parent_info = parent ? efl_key_data_get(parent, 
"exactness_info") : NULL;
+        if (parent_info) parent_info->children = 
eina_list_remove(parent_info->children, info);
+     }
+   else
+     {
+        _widgets_list.children = eina_list_remove(_widgets_list.children, 
info);
+     }
+   efl_key_data_set(event->object, "exactness_info", NULL);
+   eina_stringshare_del(info->kl_name);
+   free(info);
+}
+
+EAPI Eo *
+_efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, 
Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback)
+{
+   Eo *(*foo)(const char *, int, const Efl_Class *, Eo *, Eina_Bool, 
Eina_Bool) =
+      dlsym(RTLD_NEXT, __FUNCTION__);
+   Eo *ret = foo(file, line, klass_id, parent_id, ref, is_fallback);
+
+   if (!efl_isa(ret, EFL_CANVAS_INTERFACE) && !efl_isa(ret, 
EFL_CANVAS_OBJECT_CLASS)) goto end;
+
+   efl_event_callback_add(ret, EFL_EVENT_DEL, _obj_del, NULL);
+end:
+   return ret;
+}
+
+EOAPI void
+efl_parent_set(Eo *obj, Efl_Object *new_parent)
+{
+   void (*foo)(Eo *, Efl_Object *) = dlsym(RTLD_NEXT, __FUNCTION__);
+   Object_Info *info = NULL;
+   if (!efl_isa(obj, EFL_CANVAS_INTERFACE) && !efl_isa(obj, 
EFL_CANVAS_OBJECT_CLASS)) goto end;
+
+   info = efl_key_data_get(obj, "exactness_info");
+   if (!info)
+     {
+        info = calloc(1, sizeof(*info));
+        info->object = obj;
+        info->kl_name = eina_stringshare_add(efl_class_name_get(obj));
+        efl_key_data_set(obj, "exactness_info", info);
+     }
+
+   Eo *old_parent = efl_parent_get(obj);
+   if (info->id && old_parent == new_parent) goto end;
+   if (old_parent)
+     {
+        Object_Info *old_parent_info = efl_key_data_get(old_parent, 
"exactness_info");
+        if (old_parent_info)
+           old_parent_info->children = 
eina_list_remove(old_parent_info->children, info);
+
+        int last_parent_id = (intptr_t)efl_key_data_get(old_parent, 
info->kl_name);
+        if (info->id && last_parent_id == info->id)
+           efl_key_data_set(old_parent, info->kl_name, (void 
*)(intptr_t)(last_parent_id - 1));
+     }
+   else
+     {
+        Eina_List *itr;
+        Main_Widget_Id *wid;
+        EINA_LIST_FOREACH(_main_widget_ids, itr, wid)
+          {
+             if (info->kl_name == wid->kl_name) goto found_old_parent;
+          }
+        wid = NULL;
+found_old_parent:
+        if (wid && wid->last == info->id) wid->last--;
+        _widgets_list.children = eina_list_remove(_widgets_list.children, 
info);
+     }
+   info->id = 0;
+   info->parent = new_parent;
+   if (new_parent)
+     {
+        int last_parent_id = (intptr_t)efl_key_data_get(new_parent, 
info->kl_name);
+        info->id = ++last_parent_id;
+        efl_key_data_set(new_parent, info->kl_name, (void 
*)(intptr_t)last_parent_id);
+
+        Object_Info *new_parent_info = efl_key_data_get(new_parent, 
"exactness_info");
+        if (new_parent_info)
+           new_parent_info->children = 
eina_list_append(new_parent_info->children, info);
+     }
+   else
+     {
+        Eina_List *itr;
+        Main_Widget_Id *wid;
+        EINA_LIST_FOREACH(_main_widget_ids, itr, wid)
+          {
+             if (info->kl_name == wid->kl_name) goto found_new_parent;
+          }
+        wid = calloc(1, sizeof(*wid));
+        wid->kl_name = info->kl_name;
+        _main_widget_ids = eina_list_append(_main_widget_ids, wid);
+found_new_parent:
+        info->id = ++wid->last;
+        _widgets_list.children = eina_list_append(_widgets_list.children, 
info);
+     }
+end:
+   foo(obj, new_parent);
+}
+
+static void
+_info_fill(Object_Info *info)
+{
+   Eina_List *itr;
+   if (efl_isa(info->object, EFL_CANVAS_OBJECT_CLASS))
+      evas_object_geometry_get(info->object, &info->x, &info->y, &info->w, 
&info->h);
+   EINA_LIST_FOREACH(info->children, itr, info)
+     {
+        _info_fill(info);
+     }
+}
+
+static void
+_objects_snapshot_do()
+{
+   Eina_List *itr;
+   Object_Info *info;
+   int dir_name_len = _hook_setting->dest_dir ? 
strlen(_hook_setting->dest_dir) + 1 : 0; /* includes space of a '/' */
+   char *filename = malloc(strlen(_hook_setting->test_name) + 
strlen(OBJECTS_FILENAME_EXT) +
+         dir_name_len + 8); /* also space for serial */
+
+   if (_hook_setting->dest_dir)
+      sprintf(filename, "%s/", _hook_setting->dest_dir);
+
+   sprintf(filename + dir_name_len, "%s%c%03d%s", _hook_setting->test_name,
+         SHOT_DELIMITER, ts.serial, OBJECTS_FILENAME_EXT);
+
+   printf("%d objects saved into %s\n", 
eina_list_count(_widgets_list.children), filename);
+
+   EINA_LIST_FOREACH(_widgets_list.children, itr, info)
+     {
+        _info_fill(info);
+     }
+
+   Eet_File *file = eet_open(filename, EET_FILE_MODE_WRITE);
+   eet_data_write(file, object_info_desc_make(), "entry", &_widgets_list, 
EINA_TRUE);
+   eet_close(file);
+
+   free(filename);
+}

-- 


Reply via email to