Compare commits

...

12 Commits

Author SHA1 Message Date
Marcel Hollerbach f488b3920d exactness: error when _src_unit is NULL
if _src_unit is NULL, the write here would delete the actions, with this
commit we ensure that this is printing an error.

Differential Revision: https://phab.enlightenment.org/D11627
2020-03-31 13:07:47 +02:00
Marcel Hollerbach ee800e6f24 exactness: equip with ERR and CRIT
before a few commits, we had the situation that errors were overseen
because the log was simply so big, that errors did not get shown
properly.

With this commit, exactness will simply abort if there is a real issue
in the code.

Differential Revision: https://phab.enlightenment.org/D11624
2020-03-31 13:07:47 +02:00
Marcel Hollerbach dcd16cb590 exactness: correctly call mkdir
we should not error when mkdir returns < 0. EEXIST should not result in
the return here.

Differential Revision: https://phab.enlightenment.org/D11618
2020-03-31 13:07:47 +02:00
Marcel Hollerbach 32545f9280 exactness: do not efl_del the evas
there is no need to do that, more than that. This is super dangerous,
the display and connection ptr of x are passed from ecore_evas to evas,
if you delete evas before ecore_evas, the later ecore_evas deletion will
destroy the x connection which calls some functions in evas, which is
already freed, which leads to a crash.

Differential Revision: https://phab.enlightenment.org/D11617
2020-03-31 13:07:47 +02:00
Marcel Hollerbach fecc42715f exactness_play: introduce runner script
this is just a little python script, so you can lunch exactness_play
without the need of handdefining LD_PRELOAD

Differential Revision: https://phab.enlightenment.org/D11616
2020-03-31 13:07:47 +02:00
Marcel Hollerbach 65cc3dced8 exactness_play: transform to LD_PRELOAD library
this can now be loaded as LD_PRELOAD library

Differential Revision: https://phab.enlightenment.org/D11615
2020-03-31 13:07:47 +02:00
Marcel Hollerbach c93c016078 exactness_player: refactor main method
this refactors everything that is not argc argv related out of the main
method. For later usage

Differential Revision: https://phab.enlightenment.org/D11614
2020-03-31 13:07:47 +02:00
Marcel Hollerbach 3c69a61263 exactness: remove code for compiling
this seems to be made for compiling binaries before testing. That sounds
like a good idea, however, implementing a full buildtool in exactness is
a bit hard. Hence, using meson for that would be better.

Differential Revision: https://phab.enlightenment.org/D11613
2020-03-31 13:07:47 +02:00
Marcel Hollerbach 777209e059 exactness_record: introduce runner script
this is just a little python script, so you can lunch exactness_record
without the need of handdefining LD_PRELOAD

Differential Revision: https://phab.enlightenment.org/D11611
2020-03-31 13:07:47 +02:00
Marcel Hollerbach fd8d2748b1 exactness_recorder: move to preload
this is now not a binary anymore, that dlopen's a binary, it is now a
library, that can be loaded using LD_PRELOAD. EXACTNESS_DEST is used for
the path of the .exu file. EXACTNESS_FONTS_DIR is used to get the fonts
directory

Differential Revision: https://phab.enlightenment.org/D11610
2020-03-31 13:07:47 +02:00
Marcel Hollerbach 9cdc647001 exactness_recorder: refactor main method
all calls taht are not related to env var checking, are moved out of the
main method. That is in preparation for later refactorings.

Differential Revision: https://phab.enlightenment.org/D11623
2020-03-31 13:07:47 +02:00
Stefan Schmidt dee6866a3d Testing only 2020-03-31 13:06:20 +02:00
9 changed files with 503 additions and 381 deletions

View File

@ -76,7 +76,6 @@ jobs:
if: type = cron
env: DISTRO=Fedora31 CI_BUILD_TYPE=asan
- os: linux
if: type = cron
env: DISTRO=Fedora31-exactness CI_BUILD_TYPE=exactness
- os: linux
if: type = cron
@ -140,14 +139,3 @@ before_cache:
mv $HOME/Library/Caches/Homebrew $HOME/cachedir/Homebrew
fi
notifications:
irc:
channels:
- "chat.freenode.net#edevelop"
on_success: change
on_failure: always
template:
- "TravisCI build %{build_number} in branch %{branch}: %{result} - %{message} (%{elapsed_time})"
- "Commit: %{commit_subject} (%{commit}) from %{author}"
- "Change view : %{compare_url}"
- "Build details : %{build_url}"

View File

@ -4,6 +4,12 @@
#include "common.h"
void
ex_prepare_elm_overloay(void)
{
elm_theme_overlay_add(NULL, DATA_DIR"/exactness_play.edj");
}
int
ex_prg_invoke(const char *full_path, int argc, char **argv, Eina_Bool player)
{
@ -286,13 +292,6 @@ _unit_desc_make(void)
}
if (!unit_d)
{
Eet_Data_Descriptor *code_d = NULL;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Source_Code);
code_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(code_d, Exactness_Source_Code, "language", language, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(code_d, Exactness_Source_Code, "content", content, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(code_d, Exactness_Source_Code, "command", command, EET_T_STRING);
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action);
action_d = eet_data_descriptor_stream_new(&eddc);
@ -335,7 +334,6 @@ _unit_desc_make(void)
unit_d = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "actions", actions, action_d);
EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "objs", objs, objs_d);
EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "codes", codes, code_d);
EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "fonts_path", fonts_path, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "nb_shots", nb_shots, EET_T_UINT);
}

View File

@ -244,16 +244,6 @@ typedef struct
void *pixels; /**< Pixels of the image */
} Exactness_Image;
/**
* Description of the source code used to generate the tested application.
*/
typedef struct
{
char *language; /**< String describing the language of the content e.g "C"...*/
char *content; /**< Content used as source */
char *command; /**< Command needed to generate the application from the content */
} Exactness_Source_Code;
/**
* An Exactness test unit, including the list of tested actions and produced images.
*/
@ -263,7 +253,6 @@ typedef struct
/* imgs not in EET */
Eina_List *imgs; /**< List of Exactness_Image */
Eina_List *objs; /**< List of Exactness_Objects */
Eina_List *codes; /**< List of Exactness_Source_Code */
const char *fonts_path; /**< Path to the fonts to use, relative to the fonts dir given in parameter to the player/recorder */
int nb_shots; /**< The number of shots present in the unit */
} Exactness_Unit;
@ -278,3 +267,4 @@ void exactness_image_free(Exactness_Image *img);
int ex_prg_invoke(const char *full_path, int argc, char **argv, Eina_Bool player);
Eina_Stringshare *ex_prg_full_path_guess(const char *prg);
void ex_prepare_elm_overloay(void);

View File

@ -20,6 +20,13 @@
#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;
@ -63,8 +70,7 @@ _image_load(const char *filename)
err = evas_object_image_load_error_get(img);
if (err != EVAS_LOAD_ERROR_NONE)
{
fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
filename, evas_load_error_str(err));
CRI("Failed to load image");
return NULL;
}
@ -151,7 +157,6 @@ _exu_imgs_unpack(const char *exu_path, const char *dir, const char *ent_name)
}
efl_del(o);
}
efl_del(e);
ecore_evas_free(ee);
}
@ -171,10 +176,13 @@ _run_test_compare(const List_Entry *ent)
{
char *currentdir;
sprintf(origdir, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ORIG_SUBDIR);
if (mkdir(origdir, 0744) < 0)
if (!ecore_file_exists(origdir))
{
fprintf(stderr, "Failed to create dir %s\n", origdir);
return;
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);
@ -217,7 +225,7 @@ _run_command_prepare(const List_Entry *ent, char *buf)
sprintf(scn_path, "%s/%s.exu", base_dir, ent->name);
if (ecore_file_exists(scn_path)) goto ok;
}
fprintf(stderr, "Test %s not found in the provided base directories\n", ent->name);
CRI("Test %s not found in the provided base directories\n", ent->name);
return EINA_FALSE;
ok:
sbuf = eina_strbuf_new();
@ -318,7 +326,7 @@ _job_consume()
if (!ecore_exe_pipe_run(buf, ECORE_EXE_TERM_WITH_PARENT, ent))
{
fprintf(stderr, "Failed executing test '%s'\n", ent->name);
CRI("Failed executing test '%s'\n", ent->name);
}
}
_next_test_to_run = EINA_INLIST_CONTAINER_GET(
@ -473,9 +481,13 @@ main(int argc, char *argv[])
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)
{
@ -537,11 +549,14 @@ main(int argc, char *argv[])
ret = 1;
goto end;
}
if (mkdir(tmp, 0744) < 0)
if (!ecore_file_exists(tmp))
{
fprintf(stderr, "Failed to create dir %s", tmp);
ret = 1;
goto end;
if (mkdir(tmp, 0744) < 0)
{
fprintf(stderr, "Failed to create dir %s", tmp);
ret = 1;
goto end;
}
}
}
else if (mode_init)
@ -554,11 +569,14 @@ main(int argc, char *argv[])
ret = 1;
goto end;
}
if (mkdir(tmp, 0744) < 0)
if (!ecore_file_exists(tmp))
{
fprintf(stderr, "Failed to create dir %s", tmp);
ret = 1;
goto end;
if (mkdir(tmp, 0744) < 0)
{
fprintf(stderr, "Failed to create dir %s", tmp);
ret = 1;
goto end;
}
}
}
else if (mode_simulation)

View File

@ -0,0 +1,96 @@
#!/usr/bin/env python3
import argparse
import subprocess
import os
parser = argparse.ArgumentParser(description='A scenario recorder for EFL based applications.'
'\tF1 - Request stabilization\n'
'\tF2 - Request shot\n'
'\tF3 - Request to save the scenario\n')
parser.add_argument('app', metavar='app', help='The app to run. You can also pass environment variables here.', type=str, nargs='*')
parser.add_argument('-o', '--output', metavar='output', help=" Set the destination for the shots.\n"
" If a .exu is given, the shots are stored in the file.\n"
" Otherwise the given path is considered as a directory\n"
" where shots will be stored.\n"
" If omitted, the output type (exu or dir) is determined\n"
" by the given test extension (resp. exu or rec).", type=str)
parser.add_argument('-t', '--tests', metavar='tests', help='Name of the filename where to store the test.', type=str)
parser.add_argument('-s', '--show-on-screen', help='Show on screen', action='store_true', default=False)
parser.add_argument('--scan-objects', help='Extract information of all the objects at every shot.', action='store_true')
parser.add_argument('--external-injection', help='Expect events injection via Eina debug channel.', action='store_true')
parser.add_argument('--disable-screenshots', help='Disable screenshots.', action='store_true')
parser.add_argument('-f', '--fontsdir', metavar='fontsdir', help='Specify a directory of the fonts that should be used.', type=str)
parser.add_argument('--stabilize-shots', help='Wait for the frames to be stable before taking the shots.', action='store_true')
parser.add_argument('--speed', metavar='speed', help='Set the speed used to play the given test (default 1.0).', type=float, default=1.0)
parser.add_argument('-v', '--verbose', help='Turn verbose messages on', action='store_true')
parser.add_argument('-L', '--license', help='the path where to find the meson build directory', action='store_true')
parser.add_argument('-C', '--copyright', help='the path where to find the meson build directory', action='store_true')
parser.add_argument('-V', '--version', help='the path where to find the meson build directory', action='store_true')
G = parser.parse_args()
if G.license:
print("BSD.")
exit(0)
if G.copyright:
print("(C) 2017 Enlightenment.")
exit(0)
if G.version:
print(@VERSION@)
exit(0)
spawn_env = os.environ.copy()
spawn_env["LD_PRELOAD"] = @EXACTNESS_PLAY_PRELOAD_PATH@
if G.tests == None and G.external_injection == True:
print("no test file specified")
exit(-1)
if G.tests != None and G.external_injection == True:
print("Cannot inject events from a source file and from outside simultaneously")
exit(-1)
if G.scan_objects == True and G.tests.endswith(".exu"):
printf("Scan objects options is available only if the destination is a EXU file")
exit(-1)
if G.output != None:
spawn_env["EXACTNESS_DEST"] = G.output;
if G.external_injection:
spawn_env["EXACTNESS_EXTERNAL_INJECTION"] = "Yes"
if G.tests != None:
spawn_env["EXACTNESS_SRC"] = G.tests
if G.fontsdir != None:
spawn_env["EXACTNESS_FONTS_DIR"] = G.fontsdir
if G.speed != 1.0:
spawn_env["EXACTNESS_SPEED"] = G.speed
if G.scan_objects:
spawn_env["EXACTNESS_SCAN_OBJECTS"] = "Yes"
if G.disable_screenshots:
spawn_env["EXACTNESS_DISABLE_SHOTS"] = "Yes"
if G.stabilize_shots:
spawn_env["EXACTNESS_STABILIZE_SHOTS"] = "Yes"
if G.verbose:
spawn_env["EXACTNESS_VERBOSE"] = "Yes"
if G.show_on_screen == False:
spawn_env["ELM_DISPLAY"] = "buffer"
passed_all_the_env_vars = False
app = []
for argument in G.app:
if '=' not in argument:
passed_all_the_env_vars = True
else:
if passed_all_the_env_vars:
print("Error, env vars can only be specified at the beginning of the app call line")
exit(-1)
split_env_var = argument.split('=')
spawn_env[split_env_var[0]] = split_env_var[1]
if passed_all_the_env_vars:
app.append(argument)
recorder = subprocess.Popen(app, env=spawn_env)
recorder.wait()

View File

@ -0,0 +1,61 @@
#!/usr/bin/env python3
import argparse
import subprocess
import os
parser = argparse.ArgumentParser(description='A scenario recorder for EFL based applications.'
'\tF1 - Request stabilization\n'
'\tF2 - Request shot\n'
'\tF3 - Request to save the scenario\n')
parser.add_argument('app', metavar='app', help='The app to run. You can also pass environment variables here.', type=str, nargs='*')
parser.add_argument('-t', '--tests', metavar='tests', help='Name of the filename where to store the test.', type=str)
parser.add_argument('-f', '--fontsdir', metavar='fontsdir', help='Specify a directory of the fonts that should be used.', type=str)
parser.add_argument('-L', '--license', help='the path where to find the meson build directory', action='store_true')
parser.add_argument('-C', '--copyright', help='the path where to find the meson build directory', action='store_true')
parser.add_argument('-V', '--version', help='the path where to find the meson build directory', action='store_true')
G = parser.parse_args()
if G.license:
print("BSD.")
exit(0)
if G.copyright:
print("(C) 2017 Enlightenment.")
exit(0)
if G.version:
print(@VERSION@)
exit(0)
spawn_env = os.environ.copy()
spawn_env["LD_PRELOAD"] = @EXACTNESS_RECORD_PRELOAD_PATH@
if G.tests != None:
spawn_env["EXACTNESS_DEST"] = G.tests
else:
print("Tests dir must be passed!")
exit(-1)
if G.fontsdir != None:
spawn_env["EXACTNESS_FONTS_DIR"] = G.fontsdir
passed_all_the_env_vars = False
app = []
for argument in G.app:
if '=' not in argument:
passed_all_the_env_vars = True
else:
if passed_all_the_env_vars:
print("Error, env vars can only be specified at the beginning of the app call line")
exit(-1)
split_env_var = argument.split('=')
spawn_env[split_env_var[0]] = split_env_var[1]
if passed_all_the_env_vars:
app.append(argument)
recorder = subprocess.Popen(app, env=spawn_env)
recorder.wait()

View File

@ -30,17 +30,35 @@ edjs = custom_target('player_entry',
'@INPUT@', '@OUTPUT@'],
depends : edje_depends)
exactness_play_bin = executable('exactness_play',
exactness_play_bin = library('exactness_play',
[ 'player.c', 'common.c', 'common.h', edjs ],
dependencies: [ elementary ],
c_args: '-DDATA_DIR="'+join_paths(dir_data, 'exactness')+'"',
install: true,
)
exactness_record_bin = executable('exactness_record',
exactness_record_bin = library('exactness_record',
[ 'recorder.c', 'common.c', 'common.h' ],
dependencies: [ elementary ],
c_args: '-DDATA_DIR="'+join_paths(dir_data, 'exactness')+'"',
install: true,
)
)
exactness_env = configuration_data()
exactness_env.set_quoted('EXACTNESS_PLAY_PRELOAD_PATH', exactness_play_bin.full_path())
exactness_env.set_quoted('EXACTNESS_RECORD_PRELOAD_PATH', exactness_record_bin.full_path())
exactness_env.set_quoted('VERSION', meson.project_version())
configure_file(
input: 'exactness_record.in',
output: 'exactness_record',
configuration: exactness_env,
install_dir: get_option('bindir'),
install_mode: 'rwxr-xr-x')
configure_file(
input: 'exactness_play.in',
output: 'exactness_play',
configuration: exactness_env,
install_dir: get_option('bindir'),
install_mode: 'rwxr-xr-x')

View File

@ -7,6 +7,10 @@
#include <getopt.h>
#include <unistd.h>
#ifdef HAVE_DLSYM
# include <dlfcn.h>
#endif
#ifdef HAVE_FORK
# ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
@ -77,6 +81,7 @@ static double _speed = 1.0;
static Eina_Bool _exit_required = EINA_FALSE;
static Eina_Bool _pause_request = EINA_FALSE;
static Eina_Bool _playing_status = EINA_FALSE;
static Eina_Bool _ready_to_write = EINA_FALSE;
static Exactness_Image *
_snapshot_shot_get(Evas *e)
@ -772,6 +777,7 @@ _src_open()
if (_src_type == FTYPE_EXU)
{
_src_unit = exactness_unit_file_read(_src_filename);
_ready_to_write = EINA_TRUE;
}
if (!_src_unit) return EINA_FALSE;
if (_stabilize_shots)
@ -858,8 +864,7 @@ static Evas *
_my_evas_new(int w EINA_UNUSED, int h EINA_UNUSED)
{
Evas *e;
if (!_evas_new) return NULL;
e = _evas_new();
e = evas_new();
if (e)
{
INF("New Evas\n");
@ -869,99 +874,9 @@ _my_evas_new(int w EINA_UNUSED, int h EINA_UNUSED)
return e;
}
static const Ecore_Getopt optdesc = {
"exactness_play",
"%prog [options] <-s|-o|-v|-t|-h> command",
PACKAGE_VERSION,
"(C) 2017 Enlightenment",
"BSD",
"A scenario player for EFL based applications.",
1,
{
ECORE_GETOPT_STORE_STR('o', "output",
" Set the destination for the shots.\n"
" If a .exu is given, the shots are stored in the file.\n"
" Otherwise the given path is considered as a directory\n"
" where shots will be stored.\n"
" If omitted, the output type (exu or dir) is determined\n"
" by the given test extension"),
ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
ECORE_GETOPT_STORE_TRUE('s', "show-on-screen", "Show on screen."),
ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot."),
ECORE_GETOPT_STORE_TRUE(0, "external-injection", "Expect events injection via Eina debug channel."),
ECORE_GETOPT_STORE_TRUE(0, "disable-screenshots", "Disable screenshots."),
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_STORE_DOUBLE(0, "speed", "Set the speed used to play the given test (default 1.0)."),
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)
static Eina_Bool
_setup_dest_type(const char *dest, Eina_Bool external_injection)
{
int pret = 1, opt_args = 0;
char *src = NULL, *dest = NULL, *eq;
char *fonts_dir = NULL;
const char *chosen_fonts = NULL;
Eina_Bool show_on_screen = EINA_FALSE;
Eina_Bool want_quit = EINA_FALSE, external_injection = EINA_FALSE;
_evas_new = NULL;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_STR(dest),
ECORE_GETOPT_VALUE_STR(src),
ECORE_GETOPT_VALUE_BOOL(show_on_screen),
ECORE_GETOPT_VALUE_BOOL(_scan_objects),
ECORE_GETOPT_VALUE_BOOL(external_injection),
ECORE_GETOPT_VALUE_BOOL(_disable_shots),
ECORE_GETOPT_VALUE_STR(fonts_dir),
ECORE_GETOPT_VALUE_BOOL(_stabilize_shots),
ECORE_GETOPT_VALUE_DOUBLE(_speed),
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
};
_log_domain = eina_log_domain_register("exactness_player", NULL);
if (!ecore_evas_init())
return EXIT_FAILURE;
opt_args = ecore_getopt_parse(&optdesc, values, argc, argv);
if (opt_args < 0)
{
fprintf(stderr, "Failed parsing arguments.\n");
goto end;
}
if (want_quit) goto end;
/* Check for a sentinel */
if (argv[opt_args] && !strcmp(argv[opt_args], "--")) opt_args++;
/* Check for env variables */
do
{
eq = argv[opt_args] ? strchr(argv[opt_args], '=') : NULL;
if (eq)
{
char *var = malloc(eq - argv[opt_args] + 1);
memcpy(var, argv[opt_args], eq - argv[opt_args]);
var[eq - argv[opt_args]] = '\0';
setenv(var, eq + 1, 1);
opt_args++;
}
} while (eq);
if (dest)
{
_dest = eina_stringshare_add(dest);
@ -975,7 +890,7 @@ int main(int argc, char **argv)
if (!ecore_file_mkpath(dest))
{
fprintf(stderr, "Path for %s cannot be created\n", dest);
goto end;
return EINA_FALSE;
}
}
else
@ -984,25 +899,21 @@ int main(int argc, char **argv)
if (!ecore_file_mkpath(_dest))
{
fprintf(stderr, "Directory %s cannot be created\n", _dest);
goto end;
return EINA_FALSE;
}
}
}
if (!src && !external_injection)
{
fprintf(stderr, "no test file specified\n");
goto end;
}
if (src && external_injection)
{
fprintf(stderr, "Cannot inject events from a source file and from outside simultaneously\n");
goto end;
}
if (external_injection)
{
_src_type = FTYPE_REMOTE;
if (_dest_type == FTYPE_UNKNOWN) _dest_type = FTYPE_REMOTE;
}
return EINA_TRUE;
}
static void
_setup_names(const char *src)
{
if (src)
{
_src_filename = eina_stringshare_add(src);
@ -1021,25 +932,26 @@ int main(int argc, char **argv)
char *dot = strrchr(_test_name, '.');
if (dot) *dot = '\0';
}
}
if (_scan_objects && _dest_type != FTYPE_EXU)
{
fprintf(stderr, "Scan objects options is available only if the destination is a EXU file\n");
goto end;
}
static void
_setup_dest_unit(void)
{
if (_dest_type == FTYPE_EXU) _dest_unit = calloc(1, sizeof(*_dest_unit));
}
static void
_remove_old_shots(void)
{
if (_dest_type == FTYPE_DIR && _test_name)
eina_file_dir_list(_dest, 0, _old_shots_rm_cb, (void *)_test_name);
}
if (!_src_open())
{
fprintf(stderr, "Unable to read source file\n");
goto end;
}
if (!show_on_screen) setenv("ELM_ENGINE", "buffer", 1);
static Eina_Bool
_setup_font_settings(const char *fonts_dir)
{
const char *chosen_fonts = NULL;
if (_src_unit && _src_unit->fonts_path)
{
char buf[PATH_MAX];
@ -1049,7 +961,7 @@ int main(int argc, char **argv)
{
fprintf(stderr, "Unable to use the fonts path '%s' provided in %s\n",
_src_unit->fonts_path, _src_filename);
goto end;
return EINA_FALSE;
}
chosen_fonts = _src_unit->fonts_path;
}
@ -1059,7 +971,7 @@ int main(int argc, char **argv)
if (!ecore_file_exists(fonts_dir))
{
fprintf(stderr, "Unable to find fonts directory %s\n", fonts_dir);
goto end;
return EINA_FALSE;
}
if (!chosen_fonts)
{
@ -1082,82 +994,142 @@ int main(int argc, char **argv)
setenv("FONTCONFIG_FILE", fonts_conf_name, 1);
}
}
char **new_argv = argv;
int new_argc = argc;
if (argv[opt_args])
{
/* Replace the current command line to hide the Exactness part */
new_argv = calloc(argc - opt_args + 1, sizeof(char*));
new_argc = argc - opt_args;
for (int i = 0; i < argc - opt_args + 1; ++i)
{
if (i < argc - opt_args)
new_argv[i] = argv[opt_args + i];
else
new_argv[i] = NULL;
}
}
else
{
Eina_List *itr;
Exactness_Source_Code *code;
Eina_Tmpstr *f_output = NULL;
EINA_LIST_FOREACH(_src_unit->codes, itr, code)
{
if (!strcmp(code->language, "C") && code->command)
{
int status;
Ecore_Exe *exe;
Eina_Tmpstr *f_code;
Eina_Strbuf *sbuf;
int fd_code = eina_file_mkstemp("exactness_XXXXXX.c", &f_code);
int fd_output = eina_file_mkstemp("exactness_XXXXXX.output", &f_output);
close(fd_output);
write(fd_code, code->content, strlen(code->content));
close(fd_code);
sbuf = eina_strbuf_new();
eina_strbuf_append(sbuf, code->command);
eina_strbuf_replace_all(sbuf, "$SRC", f_code);
eina_strbuf_replace_all(sbuf, "$DEST", f_output);
exe = ecore_exe_pipe_run(eina_strbuf_string_get(sbuf), ECORE_EXE_NONE, NULL);
#ifdef HAVE_FORK
waitpid(ecore_exe_pid_get(exe), &status, 0);
#endif
}
}
if (!f_output)
{
fprintf(stderr, "no program specified\nUse -h for more information\n");
goto end;
}
argv[0] = strdup(f_output);
}
return EINA_TRUE;
}
static void
_setup_ee_creation(void)
{
ecore_evas_callback_new_set(_my_evas_new);
if (_src_type != FTYPE_REMOTE)
ecore_idler_add(_src_feed, NULL);
pret = ex_prg_invoke(ex_prg_full_path_guess(new_argv[0]), new_argc, new_argv, EINA_TRUE);
}
if (_dest && _dest_unit)
static void
_write_unit_file(void)
{
if (_dest && _dest_unit && _ready_to_write)
{
if (_src_unit)
{
Exactness_Unit *tmp = NULL;
if (_src_type == FTYPE_EXU) tmp = exactness_unit_file_read(_src_filename);
_dest_unit->actions = tmp->actions;
_dest_unit->codes = tmp->codes;
}
Exactness_Unit *tmp = NULL;
EINA_SAFETY_ON_NULL_RETURN(_src_unit);
if (_src_type == FTYPE_EXU) tmp = exactness_unit_file_read(_src_filename);
_dest_unit->actions = tmp->actions;
exactness_unit_file_write(_dest_unit, _dest);
}
end:
ecore_evas_shutdown();
eina_log_domain_unregister(_log_domain);
_log_domain = -1;
return pret;
}
#ifdef HAVE_DLSYM
# define ORIGINAL_CALL_T(t, name, ...) \
t (*_original_init_cb)(); \
_original_init_cb = dlsym(RTLD_NEXT, name); \
original_return = _original_init_cb(__VA_ARGS__);
#else
# define ORIGINAL_CALL_T(t, name, ...) \
printf("THIS IS NOT SUPPORTED ON WINDOWS\n"); \
abort();
#endif
#define ORIGINAL_CALL(name, ...) \
ORIGINAL_CALL_T(int, name, __VA_ARGS__)
EAPI int
eina_init(void)
{
int original_return;
ORIGINAL_CALL("eina_init");
if (original_return == 1)
{
const char *dest = getenv("EXACTNESS_DEST");
const char *external_injection = getenv("EXACTNESS_EXTERNAL_INJECTION");
const char *src = getenv("EXACTNESS_SRC");
const char *fonts_dir = getenv("EXACTNESS_FONTS_DIR");
const char *speed = getenv("EXACTNESS_SPEED");
_scan_objects = !!getenv("EXACTNESS_SCAN_OBJECTS");
_disable_shots = !!getenv("EXACTNESS_DISABLE_SHOTS");
_stabilize_shots = !!getenv("EXACTNESS_STABILIZE_SHOTS");
_verbose = !!getenv("EXACTNESS_VERBOSE");
if (speed)
_speed = atof(speed);
_log_domain = eina_log_domain_register("exactness_player", NULL);
if (!_setup_dest_type(dest, !!external_injection))
return 0;
_setup_names(src);
_setup_dest_unit();
_remove_old_shots();
if (!_src_open())
{
fprintf(stderr, "Unable to read source file\n");
return 0;
}
if (!_setup_font_settings(fonts_dir))
return 0;
}
return original_return;
}
EAPI int
ecore_evas_init(void)
{
int original_return;
ORIGINAL_CALL("ecore_evas_init")
if (original_return == 1)
{
_setup_ee_creation();
}
return original_return;
}
//hook, to hook in our theme
EAPI int
elm_init(int argc, char **argv)
{
int original_return;
ORIGINAL_CALL("elm_init", argc, argv)
if (original_return == 1)
ex_prepare_elm_overloay();
return original_return;
}
EAPI void
ecore_main_loop_begin(void)
{
int original_return;
ORIGINAL_CALL("ecore_main_loop_begin")
_write_unit_file();
(void)original_return;
}
EAPI Eina_Value*
efl_loop_begin(Eo *obj)
{
Eina_Value *original_return;
ORIGINAL_CALL_T(Eina_Value*, "efl_loop_begin", obj);
_write_unit_file();
return original_return;
}
EAPI int
eina_shutdown(void)
{
int original_return;
static Eina_Bool output_written = EINA_FALSE;
ORIGINAL_CALL("eina_shutdown")
if (original_return == 1 && !output_written)
{
output_written = EINA_TRUE;
_write_unit_file();
}
return original_return;
}

View File

@ -7,6 +7,10 @@
#include <getopt.h>
#include <unistd.h>
#ifdef HAVE_DLSYM
# include <dlfcn.h>
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_SYSINFO_H
# include <sys/sysinfo.h>
@ -224,8 +228,7 @@ static Evas *
_my_evas_new(int w EINA_UNUSED, int h EINA_UNUSED)
{
Evas *e;
if (!_evas_new) return NULL;
e = _evas_new();
e = evas_new();
if (e)
{
INF("New Evas\n");
@ -236,127 +239,24 @@ _my_evas_new(int w EINA_UNUSED, int h EINA_UNUSED)
return e;
}
static const Ecore_Getopt optdesc = {
"exactness_record",
"%prog [options] <-v|-t|-h> command",
PACKAGE_VERSION,
"(C) 2017 Enlightenment",
"BSD",
"A scenario recorder for EFL based applications.\n"
"\tF1 - Request stabilization\n"
"\tF2 - Request shot\n"
"\tF3 - Request to save the scenario\n",
1,
{
ECORE_GETOPT_STORE_STR('t', "test", "Name of the filename where to store the test."),
ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."),
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)
static void
_setup_unit(void)
{
char *dest = NULL, *eq;
char *fonts_dir = NULL;
int pret = 1, opt_args = 0;
Eina_Bool want_quit = EINA_FALSE;
_evas_new = NULL;
if (_unit) return;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_STR(dest),
ECORE_GETOPT_VALUE_STR(fonts_dir),
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
};
_log_domain = eina_log_domain_register("exactness_recorder", NULL);
if (!ecore_evas_init())
return EXIT_FAILURE;
opt_args = ecore_getopt_parse(&optdesc, values, argc, argv);
if (opt_args < 0)
{
fprintf(stderr, "Failed parsing arguments.\n");
goto end;
}
if (want_quit) goto end;
/* Check for a sentinel */
if (argv[opt_args] && !strcmp(argv[opt_args], "--")) opt_args++;
/* Check for env variables */
do
{
eq = argv[opt_args] ? strchr(argv[opt_args], '=') : NULL;
if (eq)
{
char *var = malloc(eq - argv[opt_args] + 1);
memcpy(var, argv[opt_args], eq - argv[opt_args]);
var[eq - argv[opt_args]] = '\0';
setenv(var, eq + 1, 1);
opt_args++;
}
} while (eq);
_out_filename = eina_stringshare_add(dest);
if (!_out_filename)
{
fprintf(stderr, "no test file specified\n");
goto end;
}
else
{
const char *_test_name;
char *slash = strrchr(_out_filename, '/');
if (slash) _test_name = strdup(slash + 1);
else _test_name = strdup(_out_filename);
char *dot = strrchr(_test_name, '.');
if (dot) *dot = '\0';
if (slash)
{
*slash = '\0';
if (!ecore_file_mkpath(_out_filename))
{
fprintf(stderr, "Can't create %s\n", _out_filename);
goto end;
}
*slash = '/';
}
}
if (strcmp(_out_filename + strlen(_out_filename) - 4,".exu"))
{
fprintf(stderr, "A file with a exu extension is required - %s invalid\n", _out_filename);
goto end;
}
if (!argv[opt_args])
{
fprintf(stderr, "no program specified\nUse -h for more information\n");
goto end;
}
if (!_unit)
{
_unit = calloc(1, sizeof(*_unit));
}
_unit = calloc(1, sizeof(*_unit));
}
static Eina_Bool
_setup_fonts_dir(const char *fonts_dir)
{
if (fonts_dir)
{
Eina_Tmpstr *fonts_conf_name = NULL;
if (!ecore_file_exists(fonts_dir))
{
fprintf(stderr, "Unable to find fonts directory %s\n", fonts_dir);
goto end;
return EINA_FALSE;
}
Eina_List *dated_fonts = ecore_file_ls(fonts_dir);
char *date_dir;
@ -376,36 +276,117 @@ int main(int argc, char **argv)
setenv("FONTCONFIG_FILE", fonts_conf_name, 1);
}
}
return EINA_TRUE;
}
/* Replace the current command line to hide the Exactness part */
char **new_argv;
new_argv = calloc(argc - opt_args + 1, sizeof(char*));
for (int i = 0; i < argc - opt_args + 1; ++i)
{
if (i < argc - opt_args)
new_argv[i] = argv[opt_args + i];
else
new_argv[i] = NULL;
}
static void
_setup_shot_key(void)
{
if (!_shot_key) _shot_key = getenv("SHOT_KEY");
if (!_shot_key) _shot_key = SHOT_KEY_STR;
}
static void
_setup_ee_creation(void)
{
ecore_evas_callback_new_set(_my_evas_new);
_last_timestamp = ecore_time_get() * 1000;
pret = ex_prg_invoke(ex_prg_full_path_guess(argv[opt_args]), argc - opt_args, new_argv, EINA_FALSE);
_output_write();
//free_events(_events_list, EINA_TRUE);
//_events_list = NULL;
pret = 0;
end:
ecore_evas_shutdown();
eina_log_domain_unregister(_log_domain);
_log_domain = -1;
return pret;
}
#ifdef HAVE_DLSYM
# define ORIGINAL_CALL_T(t, name, ...) \
t (*_original_init_cb)(); \
_original_init_cb = dlsym(RTLD_NEXT, name); \
original_return = _original_init_cb(__VA_ARGS__);
#else
# define ORIGINAL_CALL_T(t, name, ...) \
printf("THIS IS NOT SUPPORTED ON WINDOWS\n"); \
abort();
#endif
#define ORIGINAL_CALL(name, ...) \
ORIGINAL_CALL_T(int, name, __VA_ARGS__)
EAPI int
eina_init(void)
{
int original_return;
ORIGINAL_CALL("eina_init");
if (original_return == 1)
{
_log_domain = eina_log_domain_register("exactness_recorder", NULL);
_out_filename = getenv("EXACTNESS_DEST");
_setup_unit();
if (!_setup_fonts_dir(getenv("EXACTNESS_FONTS_DIR")))
return -1;
_setup_shot_key();
}
return original_return;
}
EAPI int
ecore_evas_init(void)
{
int original_return;
ORIGINAL_CALL("ecore_evas_init")
if (original_return == 1)
{
_setup_ee_creation();
}
return original_return;
}
//hook, to hook in our theme
EAPI int
elm_init(int argc, char **argv)
{
int original_return;
ORIGINAL_CALL("elm_init", argc, argv)
if (original_return == 1)
ex_prepare_elm_overloay();
return original_return;
}
EAPI void
ecore_main_loop_begin(void)
{
int original_return;
ORIGINAL_CALL("ecore_main_loop_begin")
_output_write();
(void)original_return;
}
EAPI Eina_Value*
efl_loop_begin(Eo *obj)
{
Eina_Value *original_return;
ORIGINAL_CALL_T(Eina_Value*, "efl_loop_begin", obj);
_output_write();
return original_return;
}
EAPI int
eina_shutdown(void)
{
int original_return;
static Eina_Bool output_written = EINA_FALSE;
ORIGINAL_CALL("eina_shutdown")
if (original_return == 1 && !output_written)
{
output_written = EINA_TRUE;
_output_write();
}
return original_return;
}