Revert "Revert the env object because it's broken portability - please redo"

This reverts commit d6294fa22b.
This commit is contained in:
Marcel Hollerbach 2019-02-12 21:34:27 +01:00
parent d6294fa22b
commit 06160466e8
20 changed files with 439 additions and 305 deletions

View File

@ -53,7 +53,8 @@ header_checks = [
'langinfo.h',
'locale.h',
'uv.h',
'ws2tcpip.h'
'ws2tcpip.h',
'crt_externs.h'
]
function_checks = [

View File

@ -210,6 +210,7 @@ elif sys_osx == true
sys_lib_extension = 'dylib'
sys_exe_extension = ''
sys_mod_extension = 'dylib'
config_h.set('environ', '(*_NSGetEnviron())')
else
error('System '+host_machine.system()+' not known')
endif

View File

@ -49,7 +49,9 @@ ecore_eolian_files_public = \
lib/ecore/efl_boolean_model.eo \
lib/ecore/efl_select_model.eo \
lib/ecore/efl_composite_model.eo \
lib/ecore/efl_view_model.eo
lib/ecore/efl_view_model.eo \
lib/ecore/efl_core_env.eo \
lib/ecore/efl_core_proc_env.eo \
ecore_eolian_files = \
$(ecore_eolian_files_legacy) \
@ -98,6 +100,8 @@ lib/ecore/ecore_job.c \
lib/ecore/ecore_main.c \
lib/ecore/ecore_event_message.c \
lib/ecore/ecore_event_message_handler.c \
lib/ecore/efl_core_env.c \
lib/ecore/efl_core_proc_env.c \
lib/ecore/efl_app.c \
lib/ecore/efl_loop.c \
lib/ecore/efl_loop_consumer.c \
@ -335,6 +339,7 @@ tests/ecore/efl_app_test_loop.c \
tests/ecore/efl_app_test_loop_fd.c \
tests/ecore/efl_app_test_loop_timer.c \
tests/ecore/efl_app_test_promise.c \
tests/ecore/efl_app_test_env.c \
tests/ecore/efl_app_suite.c \
tests/ecore/efl_app_suite.h

View File

@ -26,6 +26,9 @@
* @{
*/
#include "efl_core_env.eo.h"
#include "efl_core_proc_env.eo.h"
#include "efl_loop_message.eo.h"
#include "efl_loop_message_handler.eo.h"

View File

@ -188,7 +188,6 @@ struct _Efl_Task_Data
{
Eina_Stringshare *command;
Eina_Array *args;
Eina_Hash *env;
Efl_Task_Priority priority;
int exit_code;
Efl_Task_Flags flags;

View File

@ -26,7 +26,7 @@ key_valid(const char *key)
{
if (!key || key[0] == '\0') return EINA_FALSE;
if isdigit(key[0]) return EINA_FALSE;
if (isdigit(key[0])) return EINA_FALSE;
for (int i = 0; key[i] != '\0'; ++i) {
if (!isalnum(key[i]) && key[i] != '_') return EINA_FALSE;

View File

@ -0,0 +1,57 @@
class Efl.Core.Env extends Efl.Object implements Efl.Duplicate {
[[This object can maintain a set of key value pairs
A object of this type alone does not apply the object to the system.
For getting the value into the system, see @Efl.Core.Proc_Env.
A object can be forked, which will only copy its values, changes to the returned object will not change the object where it is forked off.
]]
methods {
@property env {
[[ Stored var value pairs of this object.
Var must contain only: underscores ('_'), letters ('a-z', 'A-Z'),
numbers ('0-9'), but the first character may not be a number.
]]
set {
[[ Add a new pair to this object ]]
}
get {
[[ Get the value of the $var, or $null if no such $var exists in the object]]
}
keys {
var: string; [[ The name of the variable ]]
}
values {
value: string; [[ Set var to this value if not $NULL,
otherwise clear this env value if value
is $NULL or if it is an empty string ]]
}
}
unset {
[[ Remove the pair with the matching $var from this object]]
params {
var : string; [[ The name of the variable ]]
}
}
clear {
[[ Remove all pairs from this object]]
}
@property content {
[[ Get the content of this object.
This will return a iterator that contains all keys that are part of this object.
]]
get {
}
values {
iter : iterator<string>;
}
}
}
implements {
Efl.Object.constructor;
Efl.Duplicate.duplicate;
}
}

View File

@ -0,0 +1,145 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#ifdef HAVE_CRT_EXTERNS_H
# include <crt_externs.h>
#endif
#include "ecore_private.h"
#define MY_CLASS EFL_CORE_PROC_ENV_CLASS
static Efl_Core_Env *env = NULL;
typedef struct {
Eina_Bool in_sync;
} Efl_Core_Proc_Env_Data;
static void
_sync(Efl_Core_Env *obj, Efl_Core_Proc_Env_Data *pd)
{
Eina_List *existing_keys = NULL, *n;
Eina_Iterator *content;
const char *key;
pd->in_sync = EINA_TRUE;
content = efl_core_env_content_get(obj);
EINA_ITERATOR_FOREACH(content, key)
{
existing_keys = eina_list_append(existing_keys, key);
}
if (environ)
{
char **p;
for (p = environ; *p; p++)
{
char **values;
values = eina_str_split(*p, "=", 2);
efl_core_env_set(obj, values[0], values[1]);
EINA_LIST_FOREACH(existing_keys, n, key)
{
if (!strcmp(key, values[0]))
{
existing_keys = eina_list_remove_list(existing_keys, n);
break;
}
}
}
}
EINA_LIST_FOREACH(existing_keys, n, key)
{
efl_core_env_unset(obj, key);
}
pd->in_sync = EINA_FALSE;
}
EOLIAN static const char*
_efl_core_proc_env_efl_core_env_env_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var)
{
if (!pd->in_sync)
_sync((Eo*)obj, pd);
return efl_core_env_get(efl_super(obj, MY_CLASS), var);
}
EOLIAN static void
_efl_core_proc_env_efl_core_env_env_set(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *var, const char *value)
{
efl_core_env_set(efl_super(obj, MY_CLASS), var, value);
if (!pd->in_sync)
{
if (value)
setenv(var, value, 1);
else
unsetenv(var);
}
}
EOLIAN static void
_efl_core_proc_env_efl_core_env_unset(Eo *obj, Efl_Core_Proc_Env_Data *pd, const char *key)
{
efl_core_env_unset(efl_super(obj, MY_CLASS), key);
if (!pd->in_sync)
{
unsetenv(key);
}
}
EOLIAN static void
_efl_core_proc_env_efl_core_env_clear(Eo *obj, Efl_Core_Proc_Env_Data *pd)
{
efl_core_env_clear(efl_super(obj, MY_CLASS));
if (!pd->in_sync)
{
#ifdef HAVE_CLEARENV
clearenv();
#else
environ = NULL;
#endif
}
}
EOLIAN static Efl_Duplicate*
_efl_core_proc_env_efl_duplicate_duplicate(const Eo *obj, Efl_Core_Proc_Env_Data *pd)
{
if (!pd->in_sync)
_sync((Eo*) obj, pd);
return efl_duplicate(efl_super(obj, MY_CLASS));
}
EOLIAN static Eina_Iterator*
_efl_core_proc_env_efl_core_env_content_get(const Eo *obj, Efl_Core_Proc_Env_Data *pd)
{
if (!pd->in_sync)
_sync((Eo*) obj, pd);
return efl_core_env_content_get(efl_super(obj, MY_CLASS));
}
EOLIAN static Efl_Object*
_efl_core_proc_env_efl_object_constructor(Eo *obj, Efl_Core_Proc_Env_Data *pd EINA_UNUSED)
{
EINA_SAFETY_ON_TRUE_RETURN_VAL(!!env, NULL);
obj = efl_constructor(efl_super(obj, MY_CLASS));
return obj;
}
EOLIAN static Efl_Core_Env*
_efl_core_proc_env_self(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
{
if (!env)
{
env = efl_add_ref(EFL_CORE_PROC_ENV_CLASS, NULL);
efl_wref_add(env, &env);
}
return env;
}
#include "efl_core_proc_env.eo.c"

View File

@ -0,0 +1,21 @@
class Efl.Core.Proc_Env extends Efl.Core.Env
{
eo_prefix : efl_env;
methods {
self @class {
[[Get a instance of this object
The object will apply the environment operations onto this process.
]]
return : Efl.Core.Env;
}
}
implements {
Efl.Core.Env.env { set; get; }
Efl.Core.Env.content { get; }
Efl.Core.Env.unset;
Efl.Core.Env.clear;
Efl.Duplicate.duplicate;
Efl.Object.constructor;
}
}

View File

@ -40,6 +40,7 @@ typedef struct _Efl_Exe_Data Efl_Exe_Data;
struct _Efl_Exe_Data
{
Efl_Core_Env *env;
int exit_signal;
Efl_Exe_Flags flags;
#ifdef _WIN32
@ -165,22 +166,6 @@ _exec(const char *cmd, Efl_Exe_Flags flags)
}
}
static Eina_Bool
_foreach_env(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata EINA_UNUSED)
{
int keylen;
char *buf, *s;
if (!data) return EINA_TRUE;
keylen = strlen(key);
buf = alloca(keylen + 1 + strlen(data) + 1);
strcpy(buf, key);
buf[keylen] = '=';
strcpy(buf + keylen + 1, data);
if ((s = strdup(buf))) putenv(s);
return EINA_TRUE;
}
static void
_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
{
@ -206,7 +191,7 @@ _exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
// 128+n Fatal error signal "n" kill -9 $PPID $? returns 137 (128 + 9)
// 130 Script terminated by Control-C Ctl-C Control-C is fatal error signal 2, (130 = 128 + 2, see above)
// 255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255
//
//
// According to the above table, exit codes 1 - 2,
// 126 - 165, and 255 [1] have special meanings, and
// should therefore be avoided for user-specified exit
@ -300,6 +285,25 @@ _run_clean_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,
//////////////////////////////////////////////////////////////////////////
EOLIAN static void
_efl_exe_env_set(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Core_Env *env)
{
if (pd->env == env) return;
if (!pd->env)
efl_unref(pd->env);
pd->env = env;
if (pd->env)
efl_ref(pd->env);
}
EOLIAN static Efl_Core_Env*
_efl_exe_env_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
{
return pd->env;
}
EOLIAN static void
_efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig)
{
@ -564,17 +568,28 @@ _efl_exe_efl_task_run(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
// clear systemd notify socket... only relevant for systemd world,
// otherwise shouldn't be trouble
putenv("NOTIFY_SOCKET=");
// force the env hash to update from env vars
efl_task_env_get(loop, "HOME");
// actually setenv the env hash (clear what was there before so it is
// actually setenv the env object (clear what was there before so it is
// the only env there)
#ifdef HAVE_CLEARENV
clearenv();
#else
environ = NULL;
#endif
eina_hash_foreach(td->env, _foreach_env, NULL);
if (pd->env)
{
Eina_Iterator *itr;
const char *key;
#ifdef HAVE_CLEARENV
clearenv();
#else
environ = NULL;
#endif
itr = efl_core_env_content_get(pd->env);
EINA_ITERATOR_FOREACH(itr, key)
{
setenv(key, efl_core_env_get(pd->env, key) , 1);
}
efl_unref(pd->env);
pd->env = NULL;
}
// actually execute!
_exec(cmd, pd->flags);

View File

@ -42,6 +42,23 @@ class Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Efl.Io.C
sig: int; [[ The exit signal, or -1 if no exit signal happened ]]
}
}
@property env {
[[ If $env is $null then the process created by this object is
going to inherit the enviroment of this process.
In case $env is not $null then the environment variables declared
in this object will represent the environment passed to the new process.
]]
get {
[[ Get the object assosiated with this object ]]
}
set {
[[ Set the object assosiated with this object ]]
}
values {
env : Efl.Core.Env; [[$env will be referenced until this object does not need it anymore.]]
}
}
}
implements {
Efl.Object.constructor;

View File

@ -15,8 +15,6 @@
#include "ecore_main_common.h"
extern char **environ;
typedef struct _Efl_Loop_Promise_Simple_Data Efl_Loop_Promise_Simple_Data;
typedef struct _Efl_Internal_Promise Efl_Internal_Promise;
@ -53,11 +51,6 @@ _efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loo
Eo *_mainloop_singleton = NULL;
Efl_Loop_Data *_mainloop_singleton_data = NULL;
extern Eina_Lock _environ_lock;
static Eina_List *_environ_strings_set = NULL;
static void _clean_old_environ(void);
EAPI Eo *
efl_main_loop_get(void)
{
@ -354,16 +347,6 @@ _efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
{
pd->future_message_handler = NULL;
eina_lock_take(&_environ_lock);
_clean_old_environ();
_environ_strings_set = eina_list_free(_environ_strings_set);
pd->env.environ_ptr = NULL;
free(pd->env.environ_copy);
pd->env.environ_copy = NULL;
eina_lock_release(&_environ_lock);
eina_value_flush(&pd->exit_code);
efl_destructor(efl_super(obj, EFL_LOOP_CLASS));
}
@ -674,178 +657,6 @@ efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
_app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
}
static void
_env_sync(Efl_Loop_Data *pd, Efl_Task_Data *td)
{
Eina_Bool update = EINA_FALSE;
unsigned int count = 0, i;
char **p;
// count environs
if (environ)
{
for (p = environ; *p; p++) count++;
}
// cached env ptr is the same... so look deeper if things changes
if (pd->env.environ_ptr == environ)
{
// if we have no cached copy then update
if (!pd->env.environ_copy) update = EINA_TRUE;
else
{
// if any ptr in the cached copy doesnt match environ ptr
// then update
for (i = 0; i <= count; i++)
{
if (pd->env.environ_copy[i] != environ[i])
{
update = EINA_TRUE;
break;
}
}
}
}
// cached env ptr changed so we need to update anyway
else update = EINA_TRUE;
if (!update) return;
// things changed - do the update
pd->env.environ_ptr = environ;
free(pd->env.environ_copy);
pd->env.environ_copy = NULL;
if (count > 0)
{
pd->env.environ_copy = malloc((count + 1) * sizeof(char *));
if (pd->env.environ_copy)
{
for (i = 0; i <= count; i++)
pd->env.environ_copy[i] = environ[i];
}
}
// clear previous env hash and rebuild it from environ so it matches
if (td->env) eina_hash_free(td->env);
td->env = eina_hash_string_superfast_new
((Eina_Free_Cb)eina_stringshare_del);
for (i = 0; i < count; i++)
{
char *var;
const char *value;
if (!environ[i]) continue;
if ((value = strchr(environ[i], '=')))
{
if (*value)
{
if ((var = malloc(value - environ[i] + 1)))
{
strncpy(var, environ[i], value - environ[i]);
var[value - environ[i]] = 0;
value++;
eina_hash_add(td->env, var,
eina_stringshare_add(value));
free(var);
}
}
}
}
}
static void
_clean_old_environ(void)
{
char **p;
const char *str;
Eina_List *l, *ll;
Eina_Bool ok;
// clean up old strings no longer in environ
EINA_LIST_FOREACH_SAFE(_environ_strings_set, l, ll, str)
{
ok = EINA_FALSE;
for (p = environ; *p; p++)
{
if (*p == str)
{
ok = EINA_TRUE;
break;
}
}
if (!ok)
{
_environ_strings_set =
eina_list_remove_list(_environ_strings_set, l);
eina_stringshare_del(str);
}
}
}
EOLIAN static void
_efl_loop_efl_task_env_set(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, const char *var, const char *value)
{
char *str, *str2;
size_t varlen, vallen = 0;
if (!var) return;
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
if (!td) return;
varlen = strlen(var);
if (value) vallen = strlen(value);
str = malloc(varlen + 1 + vallen + 1);
if (!str) return;
strcpy(str, var);
str[varlen] = '=';
if (value) strcpy(str + varlen + 1, value);
else str[varlen + 1] = 0;
str2 = (char *)eina_stringshare_add(str);
free(str);
if (!str2) return;
eina_lock_take(&_environ_lock);
if (putenv(str2) != 0)
{
eina_stringshare_del(str2);
eina_lock_release(&_environ_lock);
return;
}
_environ_strings_set = eina_list_append(_environ_strings_set, str2);
eina_lock_release(&_environ_lock);
efl_task_env_set(efl_super(obj, EFL_LOOP_CLASS), var, value);
eina_lock_take(&_environ_lock);
_clean_old_environ();
eina_lock_release(&_environ_lock);
}
EOLIAN static const char *
_efl_loop_efl_task_env_get(const Eo *obj, Efl_Loop_Data *pd, const char *var)
{
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
if (!td) return NULL;
eina_lock_take(&_environ_lock);
_env_sync(pd, td);
eina_lock_release(&_environ_lock);
return efl_task_env_get(efl_super(obj, EFL_LOOP_CLASS), var);
}
EOLIAN static void
_efl_loop_efl_task_env_reset(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
{
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
if (!td) return;
eina_lock_take(&_environ_lock);
#ifdef HAVE_CLEARENV
clearenv();
#else
environ = NULL;
#endif
_env_sync(pd, td);
eina_lock_release(&_environ_lock);
}
EOLIAN static Eina_Future *
_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
{

View File

@ -125,8 +125,6 @@ class Efl.Loop extends Efl.Task
Efl.Object.invalidate;
Efl.Object.destructor;
Efl.Object.provider_find;
Efl.Task.env { set; get; }
Efl.Task.env_reset;
Efl.Task.run;
Efl.Task.end;
}

View File

@ -227,19 +227,6 @@ _rebuild_command(Efl_Task_Data *pd)
eina_strbuf_free(sb);
}
static Eina_Bool
_foreach_env_copy(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata)
{
if (data)
{
// only copy env vars not already set
if (!eina_hash_find(fdata, key))
eina_hash_add(fdata, key, eina_stringshare_add(data));
}
return EINA_TRUE;
}
//////////////////////////////////////////////////////////////////////////
EOLIAN static void
@ -322,34 +309,6 @@ _efl_task_arg_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
pd->command_dirty = EINA_TRUE;
}
EOLIAN static void
_efl_task_env_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *var, const char *value)
{
if (!var) return;
if (!pd->env)
pd->env = eina_hash_string_superfast_new
((Eina_Free_Cb)eina_stringshare_del);
if (!pd->env) return;
if ((value) && (*value))
eina_hash_add(pd->env, var, eina_stringshare_add(value));
else eina_hash_del(pd->env, var, NULL);
}
EOLIAN static const char *
_efl_task_env_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *var)
{
if ((!var) || (!pd->env)) return NULL;
return eina_hash_find(pd->env, var);
}
EOLIAN static void
_efl_task_env_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
{
if (pd->env) eina_hash_free(pd->env);
pd->env = NULL;
}
EOLIAN static void
_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority)
{
@ -386,32 +345,13 @@ _efl_task_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Task_Data *pd)
eina_stringshare_del(pd->command);
pd->command = NULL;
_clear_args(pd);
if (pd->env) eina_hash_free(pd->env);
pd->env = NULL;
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd, Efl_Object *parent)
_efl_task_efl_object_parent_set(Eo *obj, Efl_Task_Data *pd EINA_UNUSED, Efl_Object *parent)
{
Eo *loop;
efl_parent_set(efl_super(obj, MY_CLASS), parent);
// copy loop env into exe task env, if not already set in env (overridden)
loop = efl_provider_find(parent, EFL_LOOP_CLASS);
if (loop)
{
Efl_Task_Data *tdl = efl_data_scope_get(loop, EFL_TASK_CLASS);
if (tdl)
{
if (!pd->env)
pd->env = eina_hash_string_superfast_new
((Eina_Free_Cb)eina_stringshare_del);
if (tdl->env)
eina_hash_foreach(tdl->env, _foreach_env_copy, pd->env);
}
}
}
//////////////////////////////////////////////////////////////////////////

View File

@ -96,26 +96,6 @@ abstract Efl.Task extends Efl.Object
[[ Clear all arguments in arg_value/count set. Will result in the
command property also being cleared. ]]
}
@property env {
[[ The environment to be passed in or that was passed to the
task. This is a string key, value list which map to environment
variables where appropriate. The var string must contain
only an underscore ('_'), letters ('a-z', 'A-Z'),
numbers ('0-9'), but the first character may not be a number.]]
set { }
get { }
keys {
var: string; [[ The variable name as a string ]]
}
values {
value: string; [[ Set var to this value if not $NULL,
otherwise clear this env value if value
is $NULL or if it is an empty string ]]
}
}
env_reset {
[[ Clear all environment variables. ]]
}
@property priority {
[[ The priority of this task. ]]
get { }

View File

@ -74,7 +74,9 @@ pub_eo_files = [
'efl_boolean_model.eo',
'efl_select_model.eo',
'efl_composite_model.eo',
'efl_view_model.eo'
'efl_view_model.eo',
'efl_core_env.eo',
'efl_core_proc_env.eo'
]
foreach eo_file : pub_eo_files
@ -180,6 +182,8 @@ ecore_src = [
'efl_thread.c',
'efl_threadio.c',
'efl_appthread.c',
'efl_core_env.c',
'efl_core_proc_env.c',
]
if sys_windows == true

View File

@ -9,7 +9,6 @@
#include "efl_app_suite.h"
#include "../efl_check.h"
EFL_START_TEST(efl_app_test_efl_build_version)
{
const Efl_Version *ver;
@ -53,6 +52,7 @@ static const Efl_Test_Case etc[] = {
{ "Promise", efl_app_test_promise_2 },
{ "Promise", efl_app_test_promise_3 },
{ "Promise", efl_app_test_promise_safety },
{ "Env", efl_test_efl_env },
{ NULL, NULL }
};

View File

@ -11,5 +11,6 @@ void efl_app_test_promise(TCase *tc);
void efl_app_test_promise_2(TCase *tc);
void efl_app_test_promise_3(TCase *tc);
void efl_app_test_promise_safety(TCase *tc);
void efl_test_efl_env(TCase *tc);
#endif /* _EFL_APP_SUITE_H */

View File

@ -0,0 +1,135 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <unistd.h>
#define EFL_NOLEGACY_API_SUPPORT
#include <Efl_Core.h>
#include "efl_app_suite.h"
#include "../efl_check.h"
EFL_START_TEST(efl_core_env_test_set_get)
{
Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
efl_core_env_set(env, "FOO", "bar");
efl_core_env_set(env, "going", "home");
efl_core_env_set(env, "Merry", "christmas");
ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar");
ck_assert_str_eq(efl_core_env_get(env, "going"), "home");
ck_assert_str_eq(efl_core_env_get(env, "Merry"), "christmas");
efl_core_env_unset(env, "Merry");
ck_assert_str_eq(efl_core_env_get(env, "FOO"), "bar");
ck_assert_str_eq(efl_core_env_get(env, "going"), "home");
ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL);
efl_unref(env);
}
EFL_END_TEST
EFL_START_TEST(efl_core_env_test_invalid_keys)
{
Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
#define CHECK(val) \
efl_core_env_set(env, val, "TEST"); \
ck_assert_ptr_eq(efl_core_env_get(env, val), NULL);
CHECK("0foo");
CHECK("foo bar");
CHECK("foo!bar");
#undef CHECK
#define CHECK(val) \
efl_core_env_set(env, val, "TEST"); \
ck_assert_str_eq(efl_core_env_get(env, val), "TEST");
CHECK("foo0");
CHECK("foo_bar");
#undef CHECK
}
EFL_END_TEST
EFL_START_TEST(efl_core_env_test_clear)
{
Efl_Core_Env *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
efl_core_env_set(env, "FOO", "bar");
efl_core_env_set(env, "going", "home");
efl_core_env_set(env, "Merry", "christmas");
efl_core_env_clear(env);
ck_assert_ptr_eq(efl_core_env_get(env, "FOO"), NULL);
ck_assert_ptr_eq(efl_core_env_get(env, "going"), NULL);
ck_assert_ptr_eq(efl_core_env_get(env, "Merry"), NULL);
efl_unref(env);
}
EFL_END_TEST
EFL_START_TEST(efl_core_env_test_fork)
{
Efl_Core_Env *env_fork, *env = efl_add_ref(EFL_CORE_ENV_CLASS, NULL);
efl_core_env_set(env, "FOO", "bar");
efl_core_env_set(env, "going", "home");
efl_core_env_set(env, "Merry", "christmas");
env_fork = efl_duplicate(env);
ck_assert_str_eq(efl_core_env_get(env_fork, "FOO"), "bar");
ck_assert_str_eq(efl_core_env_get(env_fork, "going"), "home");
ck_assert_str_eq(efl_core_env_get(env_fork, "Merry"), "christmas");
efl_unref(env);
}
EFL_END_TEST
EFL_START_TEST(efl_core_env_test_process)
{
Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS);
ck_assert(env);
ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
env_fork = efl_duplicate(env);
ck_assert_str_eq(efl_core_env_get(env_fork, "PATH"), getenv("PATH"));
efl_unref(env);
}
EFL_END_TEST
EFL_START_TEST(efl_core_env_test_undepend_fork)
{
Efl_Core_Env *env_fork, *env = efl_env_self(EFL_CORE_PROC_ENV_CLASS);
ck_assert(env);
ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
env_fork = efl_duplicate(env);
efl_core_env_set(env_fork, "PATH", "abc");
ck_assert_str_eq(efl_core_env_get(env, "PATH"), getenv("PATH"));
efl_unref(env);
efl_unref(env_fork);
}
EFL_END_TEST
void efl_test_efl_env(TCase *tc)
{
tcase_add_test(tc, efl_core_env_test_set_get);
tcase_add_test(tc, efl_core_env_test_invalid_keys);
tcase_add_test(tc, efl_core_env_test_clear);
tcase_add_test(tc, efl_core_env_test_fork);
tcase_add_test(tc, efl_core_env_test_process);
tcase_add_test(tc, efl_core_env_test_undepend_fork);
}

View File

@ -75,7 +75,8 @@ efl_app_suite_src = [
'efl_app_test_loop.c',
'efl_app_test_loop_fd.c',
'efl_app_test_loop_timer.c',
'efl_app_test_promise.c'
'efl_app_test_promise.c',
'efl_app_test_env.c'
]
efl_app_suite_deps = [m]