#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <Ecore.h>
#include <Ecore_Getopt.h>
#include <Ecore_Evas.h>
#include <Ecore_File.h>

#include "common.h"

#ifdef _WIN32
# include <evil_private.h> /* mkdir */
#endif

#define SCHEDULER_CMD_SIZE 1024

#define ORIG_SUBDIR "orig"
#define CURRENT_SUBDIR "current"

#define BUF_SIZE 1024

#define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__)
#define CRI(...) EINA_LOG_DOM_CRIT(_log_domain, __VA_ARGS__)

static int _log_domain = -1;

typedef struct
{
   EINA_INLIST;
   char *name;
   const char *command;
   double start_time;
} List_Entry;

typedef enum
{
   RUN_SIMULATION,
   RUN_PLAY,
   RUN_INIT
} Run_Mode;

static unsigned short _running_jobs = 0, _max_jobs = 1;
static Eina_List *_base_dirs = NULL;
static char *_dest_dir;
static char *_wrap_command = NULL, *_fonts_dir = NULL;
static int _verbose = 0;
static Eina_Bool _scan_objs = EINA_FALSE, _disable_screenshots = EINA_FALSE, _stabilize_shots = EINA_FALSE;

static Run_Mode _mode;
static List_Entry *_next_test_to_run = NULL;
static unsigned int _tests_executed = 0;

static Eina_List *_errors;
static Eina_List *_compare_errors;

static Eina_Bool _job_consume();

static Exactness_Image *
_image_load(const char *filename)
{
   int w, h;
   Evas_Load_Error err;
   Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
   Eo *e = ecore_evas_get(ee);

   Eo *img = evas_object_image_add(e);
   evas_object_image_file_set(img, filename, NULL);
   err = evas_object_image_load_error_get(img);
   if (err != EVAS_LOAD_ERROR_NONE)
     {
        CRI("Failed to load image");
        return NULL;
     }

   Exactness_Image *ex_img = malloc(sizeof(*ex_img));
   int len;
   evas_object_image_size_get(img, &w, &h);
   ex_img->w = w;
   ex_img->h = h;
   len = w * h * 4;
   ex_img->pixels = malloc(len);
   memcpy(ex_img->pixels, evas_object_image_data_get(img, EINA_FALSE), len);

   ecore_evas_free(ee);
   return ex_img;
}

static Eina_Bool
_image_save(Exactness_Image *ex_img, const char *output)
{
   Ecore_Evas *ee;
   Eo *e, *img;
   Eina_Bool ret = EINA_TRUE;
   ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
   e = ecore_evas_get(ee);
   img = evas_object_image_add(e);
   evas_object_image_size_set(img, ex_img->w, ex_img->h);
   evas_object_image_data_set(img, ex_img->pixels);
   if (!evas_object_image_save(img, output, NULL, NULL))
      ret = EINA_FALSE;
   ecore_evas_free(ee);
   return ret;
}

static Eina_Bool
_file_compare(const char *orig_dir, const char *ent_name)
{
   Eina_Bool result = EINA_FALSE;
   Exactness_Image *img1, *img2, *imgO = NULL;
   char *filename1 = alloca(strlen(orig_dir) + strlen(ent_name) + 20);
   char *filename2 = alloca(strlen(_dest_dir) + strlen(ent_name) + 20);
   sprintf(filename1, "%s/%s", orig_dir, ent_name);
   sprintf(filename2, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ent_name);

   img1 = _image_load(filename1);
   img2 = _image_load(filename2);

   if (exactness_image_compare(img1, img2, &imgO))
     {
        char *buf = alloca(strlen(_dest_dir) + strlen(ent_name));
        sprintf(buf, "%s/%s/comp_%s", _dest_dir, CURRENT_SUBDIR, ent_name);
        if (!_image_save(imgO, buf))
          goto cleanup;
        _compare_errors = eina_list_append(_compare_errors, strdup(ent_name));
        result = EINA_TRUE;
     }
cleanup:
   exactness_image_free(img1);
   exactness_image_free(img2);
   exactness_image_free(imgO);
   return result;
}

static void
_exu_imgs_unpack(const char *exu_path, const char *dir, const char *ent_name)
{
   Exactness_Unit *unit = exactness_unit_file_read(exu_path);
   Exactness_Image *img;
   Eina_List *itr;
   Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
   Eo *e = ecore_evas_get(ee);
   int n = 1;
   if (!unit) return;
   EINA_LIST_FOREACH(unit->imgs, itr, img)
     {
        Eo *o = evas_object_image_add(e);
        char *filename = alloca(strlen(dir) + strlen(ent_name) + 20);
        snprintf(filename, PATH_MAX, "%s/%s%c%.3d.png",
              dir, ent_name, SHOT_DELIMITER, n++);
        evas_object_image_size_set(o, img->w, img->h);
        evas_object_image_data_set(o, img->pixels);
        if (!evas_object_image_save(o, filename, NULL, NULL))
          {
             printf("Cannot save widget to <%s>\n", filename);
          }
        efl_del(o);
     }
   ecore_evas_free(ee);
}

static void
_run_test_compare(const List_Entry *ent)
{
   char *path = alloca(PATH_MAX);
   char *origdir = alloca(strlen(_dest_dir) + 20);
   const char *base_dir;
   Eina_List *itr;
   int n = 1, nb_fails = 0;
   printf("STATUS %s: COMPARE\n", ent->name);
   EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
     {
        sprintf(path, "%s/%s.exu", base_dir, ent->name);
        if (ecore_file_exists(path))
          {
             char *currentdir;
             sprintf(origdir, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ORIG_SUBDIR);
             if (!ecore_file_exists(origdir))
               {
                  if (mkdir(origdir, 0744) < 0)
                    {
                       CRI("Failed to create dir %s\n", origdir);
                       return;
                    }
               }
             _exu_imgs_unpack(path, origdir, ent->name);
             sprintf(path, "%s/%s/%s.exu", _dest_dir, CURRENT_SUBDIR, ent->name);
             currentdir = alloca(strlen(_dest_dir) + 20);
             sprintf(currentdir, "%s/%s", _dest_dir, CURRENT_SUBDIR);
             _exu_imgs_unpack(path, currentdir, ent->name);
             goto found;
          }
     }
found:
   do
     {
        sprintf(path, "%s/%s%c%.3d.png", origdir, ent->name, SHOT_DELIMITER, n);
        if (ecore_file_exists(path))
          {
             sprintf(path, "%s%c%.3d.png", ent->name, SHOT_DELIMITER, n);
             if (_file_compare(origdir, path)) nb_fails++;
          }
        else break;
        n++;
     } while (EINA_TRUE);
   if (!nb_fails)
     {
        double runtime = ecore_time_get() - ent->start_time;
        printf("STATUS %s: END - SUCCESS (time: %.2fs)\n", ent->name, runtime);
     }
   else
      printf("STATUS %s: END - FAIL (%d/%d)\n", ent->name, nb_fails, n - 1);
}

#define CONFIG "ELM_SCALE=1 ELM_FINGER_SIZE=10 "
static Eina_Bool
_run_command_prepare(List_Entry *ent, char *buf)
{
   char scn_path[PATH_MAX];
   Eina_Strbuf *sbuf;
   const char *base_dir;
   Eina_List *itr;
   EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
     {
        sprintf(scn_path, "%s/%s.exu", base_dir, ent->name);
        if (ecore_file_exists(scn_path)) goto ok;
     }
   CRI("Test %s not found in the provided base directories\n", ent->name);
   return EINA_FALSE;
ok:
   sbuf = eina_strbuf_new();
   printf("STATUS %s: START\n", ent->name);
   ent->start_time = ecore_time_get();
   eina_strbuf_append_printf(sbuf,
         "%s exactness_play %s %s%s %s%.*s %s%s%s-t '%s' ",
         _wrap_command ? _wrap_command : "",
         _mode == RUN_SIMULATION ? "-s" : "",
         _fonts_dir ? "-f " : "", _fonts_dir ? _fonts_dir : "",
         _verbose ? "-" : "", _verbose, "vvvvvvvvvv",
         _scan_objs ? "--scan-objects " : "",
         _disable_screenshots ? "--disable-screenshots " : "",
         _stabilize_shots ? "--stabilize-shots " : "",
         scn_path
         );

   if (_mode == RUN_PLAY)
      eina_strbuf_append_printf(sbuf, "-o '%s/%s/%s.exu' ", _dest_dir, CURRENT_SUBDIR, ent->name);
   if (_mode == RUN_INIT)
      eina_strbuf_append_printf(sbuf, "-o '%s' ", scn_path);

   if (ent->command)
     {
        eina_strbuf_append(sbuf, "-- ");
        eina_strbuf_append(sbuf, CONFIG);
        eina_strbuf_append(sbuf, ent->command);
     }
   strncpy(buf, eina_strbuf_string_get(sbuf), SCHEDULER_CMD_SIZE-1);
   eina_strbuf_free(sbuf);
   printf("Command: %s\n", buf);
   return EINA_TRUE;
}

static void
_job_compare(void *data)
{
   _run_test_compare(data);

   _running_jobs--;
   _job_consume();
   /* If all jobs are done. */
   if (!_running_jobs) ecore_main_loop_quit();
}

static Eina_Bool
_job_deleted_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   Ecore_Exe_Event_Del *msg = (Ecore_Exe_Event_Del *) event;
   List_Entry *ent = ecore_exe_data_get(msg->exe);

   if ((msg->exit_code != 0) || (msg->exit_signal != 0))
    {
        _errors = eina_list_append(_errors, ent);
     }

   if (_mode == RUN_PLAY)
     {
        ecore_job_add(_job_compare, ent);
     }
   else
     {
        _running_jobs--;
        _job_consume();
        if (!_running_jobs) ecore_main_loop_quit();
     }

   return ECORE_CALLBACK_RENEW;
}

static Eina_Bool
_job_consume()
{
   static Ecore_Event_Handler *job_del_callback_handler = NULL;
   char buf[SCHEDULER_CMD_SIZE];
   List_Entry *ent = _next_test_to_run;

   if (_running_jobs == _max_jobs) return EINA_FALSE;
   if (!ent) return EINA_FALSE;

   if (_run_command_prepare(ent, buf))
     {
        _running_jobs++;
        _tests_executed++;

        if (!job_del_callback_handler)
          {
             job_del_callback_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
                   _job_deleted_cb, NULL);
          }

        if (!ecore_exe_pipe_run(buf, ECORE_EXE_TERM_WITH_PARENT, ent))
          {
             CRI("Failed executing test '%s'\n", ent->name);
          }
     }
   _next_test_to_run = EINA_INLIST_CONTAINER_GET(
         EINA_INLIST_GET(ent)->next, List_Entry);


   return EINA_TRUE;
}

static void
_scheduler_run()
{
   while (_job_consume());
}

static List_Entry *
_list_file_load(const char *filename)
{
   List_Entry *ret = NULL;
   char buf[BUF_SIZE] = "";
   FILE *file;
   file = fopen(filename, "r");
   if (!file)
     {
        perror("Failed opening list file");
        return NULL;
     }

   while (fgets(buf, BUF_SIZE, file))
     {
        /* Skip comment/empty lines. */
        if ((*buf == '#') || (*buf == '\n') || (!*buf))
           continue;

        char *tmp;
        List_Entry *cur = calloc(1, sizeof(*cur));
        cur->name = strdup(buf);

        /* Set the command to the second half and put a \0 in between. */
        tmp = strchr(cur->name, ' ');
        if (tmp)
          {
             *tmp = '\0';
             cur->command = tmp + 1;
          }
        else
          {
             /* FIXME: error. */
             cur->command = "";
          }

        /* Replace the newline char with a \0. */
        tmp = strchr(cur->command, '\n');
        if (tmp)
          {
             *tmp = '\0';
          }

        ret = EINA_INLIST_CONTAINER_GET(
              eina_inlist_append(EINA_INLIST_GET(ret), EINA_INLIST_GET(cur)),
              List_Entry);
     }

   fclose(file);
   return ret;
}

static void
_list_file_free(List_Entry *list)
{
   while (list)
     {
        List_Entry *ent = list;
        list = EINA_INLIST_CONTAINER_GET(EINA_INLIST_GET(list)->next,
              List_Entry);

        free(ent->name);
        free(ent);
        /* we don't free ent->command because it's allocated together. */
     }
}

static int
_errors_sort_cb(List_Entry *a, List_Entry *b)
{
   return strcmp(a->name, b->name);
}

static const Ecore_Getopt optdesc = {
  "exactness",
  "%prog [options] <-p|-i|-s> <test list file>",
  PACKAGE_VERSION,
  "(C) 2013-2020 Enlightenment",
  "BSD",
  "A pixel-perfect test suite for EFL-based applications.\n"
  "\n"
  "This binary allows running the individual tools `exactness_record` and\n"
  "`exactness_play` in batch for a set of tests specified in a test list file.\n"
  "\n"
  "To obtain the reference templates (the \"golden\" files):\n"
  "1.For each tested application, run `exactness_record` to launch the\n"
  "   application and record actions like keystrokes and mouse clicks.\n"
  "   This produces a test file with `.exu` extension.\n"
  "2.Run `exactness` in init mode (-i) to execute the stored actions in all\n"
  "   the tests in the test list file and obtain screenshots.\n"
  "   The screenshots are embedded into the test `.exu` file.\n"
  "\n"
  "To check if the application currently matches the reference templates:\n"
  "1.Run `exactness` in play mode (-p) to execute the stored actions in all\n"
  "   the tests in the test list file and compare the obtained screenshots\n"
  "   with the stored versions (the reference templates).\n"
  "   If mismatches are detected an error report is produced, including\n"
  "   a graphical diff of the screenshots.\n"
  "\n"
  "The test list file contains one line per test. Each line starts with the\n"
  "test file name (without the `.exu` extension), a space and then the command\n"
  "to execute, including parameters if any. # indicates a comment.\n"
  "Example:\n"
  "separator elementary_test -to Separator",
  0,
  {
    ECORE_GETOPT_APPEND('b', "base-dir", "The location of the exu files. Defaults to `./recordings/`.",
      ECORE_GETOPT_TYPE_STR),
    ECORE_GETOPT_STORE_STR('o', "output", "The location of the images. Defaults to `./`."),
    ECORE_GETOPT_STORE_STR('w', "wrap", "Use a custom command to launch the tests (e.g valgrind)."),
    ECORE_GETOPT_STORE_USHORT('j', "jobs", "The number of jobs to run in parallel. Defaults to 1."),
    ECORE_GETOPT_STORE_TRUE('p', "play", "Run in play mode. Actions are executed and obtained "
      "screenshots are compared to the stored version (golden templates)."),
    ECORE_GETOPT_STORE_TRUE('i', "init", "Run in init mode. Actions are executed and obtained "
      "screenshots are stored to be used as golden templates in the future."),
    ECORE_GETOPT_STORE_TRUE('s', "simulation", "Run in simulation mode. Actions are executed and "
      "displayed but no screenshot is obtained. Useful for debugging."),
    ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot (UNUSED)."),
    ECORE_GETOPT_STORE_TRUE(0, "disable-screenshots", "Disable screenshots. Only checks that actions "
      "can be performed and the application does not crash."),
    ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."),
    ECORE_GETOPT_STORE_TRUE(0, "stabilize-shots", "Wait for the frames to be stable before taking the shots."),
    ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),

    ECORE_GETOPT_LICENSE('L', "license"),
    ECORE_GETOPT_COPYRIGHT('C', "copyright"),
    ECORE_GETOPT_VERSION('V', "version"),
    ECORE_GETOPT_HELP('h', "help"),
    ECORE_GETOPT_SENTINEL
  }
};

int
main(int argc, char *argv[])
{
   int ret = 0;
   List_Entry *test_list;
   int args = 0;
   const char *list_file;
   Eina_List *itr;
   const char *base_dir;
   char tmp[PATH_MAX];
   Eina_Bool mode_play = EINA_FALSE, mode_init = EINA_FALSE, mode_simulation = EINA_FALSE;
   Eina_Bool want_quit = EINA_FALSE, scan_objs = EINA_FALSE;
   Ecore_Getopt_Value values[] = {
     ECORE_GETOPT_VALUE_LIST(_base_dirs),
     ECORE_GETOPT_VALUE_STR(_dest_dir),
     ECORE_GETOPT_VALUE_STR(_wrap_command),
     ECORE_GETOPT_VALUE_USHORT(_max_jobs),
     ECORE_GETOPT_VALUE_BOOL(mode_play),
     ECORE_GETOPT_VALUE_BOOL(mode_init),
     ECORE_GETOPT_VALUE_BOOL(mode_simulation),
     ECORE_GETOPT_VALUE_BOOL(scan_objs),
     ECORE_GETOPT_VALUE_BOOL(_disable_screenshots),
     ECORE_GETOPT_VALUE_STR(_fonts_dir),
     ECORE_GETOPT_VALUE_BOOL(_stabilize_shots),
     ECORE_GETOPT_VALUE_INT(_verbose),

     ECORE_GETOPT_VALUE_BOOL(want_quit),
     ECORE_GETOPT_VALUE_BOOL(want_quit),
     ECORE_GETOPT_VALUE_BOOL(want_quit),
     ECORE_GETOPT_VALUE_BOOL(want_quit),
     ECORE_GETOPT_VALUE_NONE
   };

   if (!ecore_evas_init())
      return EXIT_FAILURE;

   _log_domain = eina_log_domain_register("exactness", "red");
   _dest_dir = "./";
   _scan_objs = scan_objs;

   eina_log_abort_on_critical_set(EINA_TRUE);
   eina_log_abort_on_critical_level_set(EINA_LOG_LEVEL_ERR);

   args = ecore_getopt_parse(&optdesc, values, argc, argv);
   if (args < 0)
     {
        fprintf(stderr, "Failed parsing arguments.\n");
        ret = 1;
        goto end;
     }
   else if (want_quit)
     {
        ret = 1;
        goto end;
     }
   else if (args == argc)
     {
        fprintf(stderr, "Expected test list file as the last argument..\n");
        ecore_getopt_help(stderr, &optdesc);
        ret = 1;
        goto end;
     }
   else if (mode_play + mode_init + mode_simulation != 1)
     {
        fprintf(stderr, "Exactly one running mode must be set.\n");
        ecore_getopt_help(stderr, &optdesc);
        ret = 1;
        goto end;
     }

   if (!_base_dirs) _base_dirs = eina_list_append(NULL, "./recordings");

   list_file = argv[args];

   /* Load the list file and start iterating over the records. */
   test_list = _list_file_load(list_file);
   _next_test_to_run = test_list;

   if (!test_list)
     {
        fprintf(stderr, "No matching tests found in list file '%s'\n", list_file);
        ret = 1;
        goto end;
     }

   /* Pre-run summary */
   fprintf(stderr, "Running with settings:\n");
   fprintf(stderr, "\tConcurrent jobs: %d\n", _max_jobs);
   fprintf(stderr, "\tTest list file: %s\n", list_file);
   fprintf(stderr, "\tBase dirs:\n");
   EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
      fprintf(stderr, "\t\t%s\n", base_dir);
   fprintf(stderr, "\tDest dir: %s\n", _dest_dir);

   if (mode_play)
     {
        _mode = RUN_PLAY;
        if (snprintf(tmp, PATH_MAX, "%s/%s", _dest_dir, CURRENT_SUBDIR)
            >= PATH_MAX)
          {
             fprintf(stderr, "Path too long: %s", tmp);
             ret = 1;
             goto end;
          }
        if (!ecore_file_exists(tmp))
          {
             if (mkdir(tmp, 0744) < 0)
               {
                  fprintf(stderr, "Failed to create dir %s", tmp);
                  ret = 1;
                  goto end;
               }
          }
     }
   else if (mode_init)
     {
        _mode = RUN_INIT;
        if (snprintf(tmp, PATH_MAX, "%s/%s", _dest_dir, ORIG_SUBDIR)
            >= PATH_MAX)
          {
             fprintf(stderr, "Path too long: %s", tmp);
             ret = 1;
             goto end;
          }
        if (!ecore_file_exists(tmp))
          {
             if (mkdir(tmp, 0744) < 0)
               {
                  fprintf(stderr, "Failed to create dir %s", tmp);
                  ret = 1;
                  goto end;
               }
          }
     }
   else if (mode_simulation)
     {
        _mode = RUN_SIMULATION;
     }
   _scheduler_run();


   ecore_main_loop_begin();

   /* Results */
   printf("*******************************************************\n");
   if (mode_play && EINA_FALSE)
     {
        List_Entry *list_itr;

        EINA_INLIST_FOREACH(test_list, list_itr)
          {
             _run_test_compare(list_itr);
          }
     }

   printf("Finished executing %u out of %u tests.\n",
         _tests_executed,
         eina_inlist_count(EINA_INLIST_GET(test_list)));
   printf("%u tests executed\n", _tests_executed);
   printf("%u tests had execution errors\n", eina_list_count(_errors));
   printf("%u screenshots failed comparison\n", eina_list_count(_compare_errors));

   /* Sort the errors and the compare_errors. */
   _errors = eina_list_sort(_errors, 0, (Eina_Compare_Cb) _errors_sort_cb);
   _compare_errors = eina_list_sort(_compare_errors, 0, (Eina_Compare_Cb) strcmp);

   if (_errors || _compare_errors)
     {
        FILE *report_file;
        char report_filename[PATH_MAX] = "";
        /* Generate the filename. */
        snprintf(report_filename, PATH_MAX,
              "%s/%s/errors.html",
              _dest_dir, mode_init ? ORIG_SUBDIR : CURRENT_SUBDIR);
        report_file = fopen(report_filename, "w+");
        if (report_file)
          {
             fprintf(report_file,
                   "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
                   "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>Exactness report</title></head><body>");

             if (_errors)
               {
                  fprintf(report_file,
                        "<h1>Tests that failed execution:</h1><ul>");
                  List_Entry *ent;
                  printf("List of tests that failed execution:\n");
                  EINA_LIST_FOREACH(_errors, itr, ent)
                    {
                       printf("\t* %s\n", ent->name);

                       fprintf(report_file, "<li>%s</li>", ent->name);
                    }
                  fprintf(report_file, "</ul>");
               }

             if (_compare_errors)
               {
                  fprintf(report_file,
                        "<h1>Images that failed comparison: (Original, Current, Diff)</h1><ul>");
                  char *test_name;
                  printf("List of images that failed comparison:\n");
                  EINA_LIST_FREE(_compare_errors, test_name)
                    {
                       Eina_Bool is_from_exu;
                       char origpath[PATH_MAX];
                       snprintf(origpath, PATH_MAX, "%s/%s/orig/%s",
                             _dest_dir, CURRENT_SUBDIR, test_name);
                       is_from_exu = ecore_file_exists(origpath);
                       printf("\t* %s\n", test_name);

                       fprintf(report_file, "<li><h2>%s</h2> <img src='%sorig/%s' alt='Original' /> <img src='%s' alt='Current' /> <img src='comp_%s' alt='Diff' /></li>",
                             test_name, is_from_exu ? "" : "../",
                             test_name, test_name, test_name);
                       free(test_name);
                    }
                  fprintf(report_file, "</ul>");
               }
             fprintf(report_file,
                   "</body></html>");

             printf("Report html: %s\n", report_filename);
             ret = 1;
          }
        else
          {
             perror("Failed opening report file");
          }
     }

   _list_file_free(test_list);
end:
   ecore_evas_shutdown();

   return ret;
}
