summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLarry Lira <larry@expertisesolutions.com.br>2018-09-04 20:47:23 -0300
committerLauro Moura <lauromoura@expertisesolutions.com.br>2019-10-24 21:16:23 -0300
commit33893ffc74909de4b6357f0b05d10354661401df (patch)
treed2b18d12596e3c919cc1c49f77453b48e4938d12
parentca0052f9cf4f4e862a89b57c907d7f311aa99694 (diff)
downloadefl-devs/lauromoura/tcautomated-squashed.tar.gz
eolian: Added Eolian test generatordevs/lauromoura/tcautomated-squashed
The test generator allows templates to be used to generate boilerplate for unit tests Some automated tests were giving different results regarding @cref Slices
-rw-r--r--src/scripts/pyolian/pyratemp.py2
-rw-r--r--src/scripts/testgen/README.md146
-rw-r--r--src/scripts/testgen/__init__.py0
-rw-r--r--src/scripts/testgen/ekeys.py272
-rw-r--r--src/scripts/testgen/name_helpers.py92
-rw-r--r--src/scripts/testgen/suitegen.py291
-rwxr-xr-xsrc/scripts/testgen/testgen.py125
-rw-r--r--src/scripts/testgen/testgenerator.c.template187
-rw-r--r--src/scripts/testgen/testgenerator.cs.template113
-rw-r--r--src/tests/automated/ecore_audio_custom.c3
-rw-r--r--src/tests/automated/ecore_audio_init.c2
-rw-r--r--src/tests/automated/ecore_audio_out/input_attach/arg_init.c1
-rw-r--r--src/tests/automated/ecore_audio_out/input_detach/arg_init.c1
-rw-r--r--src/tests/automated/ecore_audio_out_wasapi/init.c3
-rw-r--r--src/tests/automated/ecore_audio_out_wasapi/shutdown.c3
-rw-r--r--src/tests/automated/ector_custom.c3
-rw-r--r--src/tests/automated/ector_init.c1
-rw-r--r--src/tests/automated/ector_renderer_cairo_shape/init.c2
-rw-r--r--src/tests/automated/ector_shutdown.c1
-rw-r--r--src/tests/automated/edje_custom.c1
-rw-r--r--src/tests/automated/edje_init.c2
-rw-r--r--src/tests/automated/edje_shutdown.c2
-rw-r--r--src/tests/automated/efl_canvas_layout_part/init.c9
-rw-r--r--src/tests/automated/efl_canvas_layout_part_box/init.c9
-rw-r--r--src/tests/automated/efl_canvas_layout_part_external/init.c8
-rw-r--r--src/tests/automated/efl_canvas_layout_part_swallow/init.c8
-rw-r--r--src/tests/automated/efl_canvas_layout_part_table/init.c8
-rw-r--r--src/tests/automated/efl_canvas_layout_part_text/init.c8
-rw-r--r--src/tests/automated/efl_canvas_video/init.c2
-rw-r--r--src/tests/automated/efl_loop/begin/init.c9
-rw-r--r--src/tests/automated/efl_loop/begin/shutdown.c3
-rw-r--r--src/tests/automated/efl_loop/custom.c5
-rw-r--r--src/tests/automated/efl_loop/timeout/arg_init.c1
-rw-r--r--src/tests/automated/efl_text_markup_util/init.c1
-rw-r--r--src/tests/automated/eio_custom.c1
-rw-r--r--src/tests/automated/eio_init.c1
-rw-r--r--src/tests/automated/eio_shutdown.c1
-rw-r--r--src/tests/automated/eldbus_init.c1
-rw-r--r--src/tests/automated/eldbus_shutdown.c1
-rw-r--r--src/tests/automated/emotion_custom.c2
-rw-r--r--src/tests/automated/emotion_init.c3
-rw-r--r--src/tests/automated/emotion_shutdown.c4
-rw-r--r--src/tests/automated/evas_custom.c1
43 files changed, 1339 insertions, 0 deletions
diff --git a/src/scripts/pyolian/pyratemp.py b/src/scripts/pyolian/pyratemp.py
index c28e260b4b..1ddfb773fc 100644
--- a/src/scripts/pyolian/pyratemp.py
+++ b/src/scripts/pyolian/pyratemp.py
@@ -846,6 +846,8 @@ class EvalPseudoSandbox:
"complex" : builtins.complex,
"dict" : builtins.dict,
"enumerate" : builtins.enumerate,
+ "filter" : builtins.filter,
+ "next" : builtins.next,
"float" : builtins.float,
"int" : builtins.int,
"list" : builtins.list,
diff --git a/src/scripts/testgen/README.md b/src/scripts/testgen/README.md
new file mode 100644
index 0000000000..4531f636db
--- /dev/null
+++ b/src/scripts/testgen/README.md
@@ -0,0 +1,146 @@
+
+Testgen: Template-based Eolian tests generator
+===============================================================================
+
+Testgen is a Python Script using the Pyolian to generate tests rendering
+templates with custom files, this can be a easy way to expand the
+API test coveraged.
+
+Testgen can generate tests C and to other bingings languages only
+adding new language specialized templates.
+
+Installation
+============
+
+There is nothing to install to use the generator, everything is included in
+the efl source tree and it is intended to work directly inside the tree,
+usually at efl tests compilation time (make check).
+
+The only requirement is that **the source tree must be already built** (not
+installed) because pyolian search the eolian .so/.dll inside the source tree.
+
+If you built the efl tree in a custom location (fe, you build out-of-tree) you
+can tell pyolian where to find the built eolian .so files using the
+`EOLIAN_SO_DIR` environment variable.
+
+
+Command line usage
+==================
+
+The simplest way to use the generator is from the command line, using the
+`src/scripts/testgen/testgen.py` command, the `--help` option state:
+
+```
+usage: testgen.py [-h] testname suitename filename [eofiles [eofiles ...]]
+
+Eolian Test Generator.
+
+positional arguments:
+ testname The Test Name used to find custom and template files. (REQUIRED)
+ suitename The Suite Name used to find custom files. (REQUIRED)
+ filename Generated test file destination. (REQUIRED)
+ eofiles The Eolian Files to use.
+
+optional arguments:
+ -h, --help show this help message and exit
+```
+Use .c extension in <filename> to generate C tests or .cs to CSharp
+
+To test this generator in `src/scripts/testgen` you can run:
+```
+./testgen.py automated efl efl_automated_test.c efl_loop.eo
+```
+This will rendere the automated tests using files in `src/tests/automated` with
+suite name `efl_automated` and with Efl.Loop Class as Test Case
+`efl_automated_efl_loop_test`
+
+or run:
+```
+./testgen.py automated eio eio_automated_test.c eio_sentry.eo eio_model.eo
+```
+This will rendere with suite name `eio_automated` and with Eio.Sentry and
+Eio.Model Class as Test Cases `eio_automated_eio_sentry_test` and
+`eio_automated_eio_model_test`
+
+
+How customise a Generated Test
+==============================
+
+Testgen use the filesystem to find custom files if you need customise a test,
+add/write follow files in src/tests:
+
+ Suite custom files
+ * `src/test/<testname>/`
+ |-> <suitename>_custom.c #add include files, functions or structs
+ |-> <suitename>_init.c #add code in SUITE_INIT
+ |-> <suitename>_shutdown.c #add code in SUITE_SHUTDOWN
+
+ Class Test case custom files
+ * `src/test/<testname>/<class_name>/` #use lowercase and `_` separator
+ |-> custom.c #add include files, functions or structs
+ |-> init.c #add default way to create the object of this class
+ |-> shutdown.c #add default way to free the object
+
+Funtions Tests
+- Tests methodes custom files
+ * `src/test/<testname>/<class_name>/<method_name>`
+ |-> arg_init.c #initialize method arguments (arg_<argument_name>)
+ |-> init.c #add how to create the object (replace default)
+ |-> arg_shutdown.c #free arguments
+ |-> shutdown.c #add how to free the object (replace default)
+
+- Tests properties custom files
+ * `src/test/<testname>/<class_name>/<property_name>`
+ | -- Property Get --
+ |-> arg_get_init.c #initialize property get arguments (arg_<argument_name>)
+ |-> get_init.c #how to create the object (replace default)
+ |-> arg_get_shutdown.c #free arguments
+ |-> get_shutdown.c #how to free the object (replace default)
+ | -- Property Set --
+ |-> arg_set_init.c #initialize propety set arguments (arg_<argument_name>)
+ |-> set_init.c #how to create the object (replace default)
+ |-> arg_set_shutdown.c #free arguments
+ |-> set_shutdown.c #how to free the object (replace default)
+
+Event Tests
+- Tests Events custom files
+ * `src/test/<testname>/<class_name>/<event_name>/`
+ |-> init.cs #add how to initialize the objects
+ |-> custom.cs #add customizations in callback
+ |-> shutdown.cs #add shutdown or any method to call the event
+
+to make some custom files you only need a code using:
+ `parent` -> default name of parent object defined as `Eo *`
+ `obj` -> default name of current object
+ `arg_<name>` -> replace <name> with functions arguments name
+
+you can use custom.c (suite or class) to add specilized code, structs and callbacks
+
+-- Use `*.cs` to Emono/CSharp generated code --
+
+Some class or function test don't need a test in some Suite, you can disable test generated
+of it with a blank file as following:
+
+use lowercase and `_` as separator
+`src/test/<testname>/<class_name>` #don't generate test for <class_name>
+`src/test/<testname>/<class_name>/method_name` #don't generate test for <method_name>
+`src/test/<testname>/<class_name>/<property_name>` #don't generate test for this property
+`src/test/<testname>/<class_name>/<property_name>_get` #don't generate test for this property get
+`src/test/<testname>/<class_name>/<property_name>_set` #don't generate test for this property set
+
+
+Where to find more info
+=======================
+
+ * read the Pyolian README file in EFL scripts
+ * read the eolian.py file (it declare the full eolian API)
+ * read the generator.py file (it's super simple)
+ * read the original [pyratemp docs](https://www.simple-is-better.org/template/pyratemp.html)
+
+
+Note
+====
+
+This markdown file is mirrored in efl src tree (src/scripts/pyolian) and in
+phab wiki (phab.enlightenment.org/w/pyolian). Don't forget to update the other
+if you change one!
diff --git a/src/scripts/testgen/__init__.py b/src/scripts/testgen/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/scripts/testgen/__init__.py
diff --git a/src/scripts/testgen/ekeys.py b/src/scripts/testgen/ekeys.py
new file mode 100644
index 0000000000..42d9889f8d
--- /dev/null
+++ b/src/scripts/testgen/ekeys.py
@@ -0,0 +1,272 @@
+#!/usr/bin/env python3
+# encoding: utf-8
+from enum import IntEnum, IntFlag
+
+from testgen import name_helpers
+
+
+class Function_List_Type(IntFlag):
+ OWN = 1
+ IMPLEMENTS = 2 # Overrides
+ EXTENSIONS = 4 # Interfaces/Mixins
+ INHERITED = 8 # Inherited but not overriden methods and classes
+ INHERITS_FULL = 4 & 8
+
+
+class EKeys:
+ def __init__(self, ext):
+ self.ext = ext
+ self.dicttypes = {}
+ self.keywords = []
+ self.verbs = []
+ self.blacklist = ["efl_constructor"]
+ self.keyloads = ["init", "shutdown", "custom"]
+ self.implementsbl = ["construtor", "destructor", "finalize"]
+ self.funclist = Function_List_Type.OWN | Function_List_Type.IMPLEMENTS
+
+ def type_convert(self, eotype):
+ return eotype.name
+
+ def event_convert(self, event):
+ return event.c_macro
+
+ def print_arg(self, eoarg):
+ return "arg_{}".format(eoarg.name)
+
+ def format_name(self, func):
+ return self.name
+
+
+class EMonoKeys(EKeys):
+ def __init__(self, ext):
+ super().__init__(ext)
+ self.funclist = (
+ Function_List_Type.OWN
+ | Function_List_Type.IMPLEMENTS
+ | Function_List_Type.EXTENSIONS
+ )
+ self.dicttypes = {
+ "byte": "sbyte",
+ "llong": "long",
+ "int8": "sbyte",
+ "int16": "short",
+ "int32": "int",
+ "int64": "long",
+ "ssize": "long",
+ "ubyte": "byte",
+ "ullong": "ulong",
+ "uint8": "byte",
+ "uint16": "ushort",
+ "uint32": "uint",
+ "uint64": "ulong",
+ "size": "ulong",
+ "ptrdiff": "long",
+ "intptr": "System.IntPtr",
+ "uintptr": "System.IntPtr",
+ "void_ptr": "System.IntPtr",
+ "void": "System.IntPtr", # only if is out/inout
+ "Error": "Eina.Error",
+ "string": "System.String",
+ "mstring": "System.String",
+ "stringshare": "System.String",
+ "any_value": "Eina.Value",
+ "any_value_ptr": "Eina.Value"
+ # complex Types
+ ,
+ "list": "Eina.List",
+ "inlist": "Eina.Inlist",
+ "array": "Eina.Array",
+ "inarray": "Eina.Inarray",
+ "hash": "Eina.Hash",
+ "promise": "int",
+ "future": "int",
+ "iterator": "Eina.Iterator",
+ "accessor": "Eina.Accessor",
+ "strbuf": "Eina.Strbuf",
+ "Efl.Class": "System.Type",
+ "rw_slice": "Eina.RwSlice",
+ "slice": "Eina.Slice",
+ }
+
+ self.keywords = [
+ "delete",
+ "do",
+ "lock",
+ "event",
+ "in",
+ "object",
+ "interface",
+ "string",
+ "internal",
+ "fixed",
+ "base",
+ ]
+
+ self.verbs = [
+ "add",
+ "get",
+ "is",
+ "del",
+ "thaw",
+ "freeze",
+ "save",
+ "wait",
+ "eject",
+ "raise",
+ "lower",
+ "load",
+ "dup",
+ "reset",
+ "unload",
+ "close",
+ "set",
+ "interpolate",
+ "has",
+ "grab",
+ "check",
+ "find",
+ "ungrab",
+ "unset",
+ "clear",
+ "pop",
+ "new",
+ "peek",
+ "push",
+ "update",
+ "show",
+ "move",
+ "hide",
+ "calculate",
+ "resize",
+ "attach",
+ "pack",
+ "unpack",
+ "emit",
+ "call",
+ "append",
+ ]
+
+ self.blacklist = [
+ "efl_event_callback_array_priority_add",
+ "efl_event_callback_forwarder_priority_add",
+ "efl_player_position_get",
+ "efl_text_font_source",
+ "efl_ui_focus_manager_focus_get",
+ "efl_ui_widget_focus",
+ "efl_ui_text_password",
+ "elm_interface_scrollable_repeat_events",
+ "elm_wdg_item_del",
+ "elm_wdg_item_focus",
+ "elm_interface_scrollable_mirrored_set",
+ "evas_obj_table_mirrored",
+ "edje_obj_load_error_get",
+ "efl_ui_focus_user_parent_get",
+ "efl_canvas_object_scale", # duplicated signature
+ "efl_access_parent_get",
+ "efl_access_name",
+ "efl_access_root_get",
+ "efl_access_type_get",
+ "efl_access_role_get",
+ "efl_access_action_description",
+ "efl_access_image_description",
+ "efl_access_component_layer_get", # duplicated signature
+ "efl_access_component_alpha_get",
+ "efl_access_component_size_get",
+ "efl_ui_spin_button_loop_get",
+ "efl_ui_list_model_size_get",
+ "efl_ui_list_relayout_layout_do",
+ "efl_constructor",
+ ]
+
+ self.struct_blacklist = [
+ "Efl.Event_Description",
+ "Eina.Binbuf",
+ "Eina.Strbuf",
+ "Eina.Slice",
+ "Eina.Rw_Slice",
+ "Eina.Promise",
+ "Eina.Value",
+ "Eina.Value_Type",
+ "Eina.Future",
+ ]
+
+ def escape_keyword(self, key):
+ key = "kw_{}".format(key) if key in self.keywords else key
+ return "{}Add".format(key) if key == "Finalize" else key
+
+ def direction_get(self, param):
+ direction = param.direction
+
+ if direction == direction.INOUT:
+ return "ref"
+ elif direction != direction.IN:
+ if param.type.name in ("slice", "rw_slice"):
+ return "ref"
+ else:
+ return "out"
+ elif (direction == direction.IN) and param.type.is_ptr:
+ if param.type.typedecl and (
+ param.type.typedecl.type == param.type.typedecl.type.STRUCT
+ ):
+ return "ref" if param.type.name not in self.struct_blacklist else None
+
+ return None
+
+ def klass_name(self, eotype):
+ *namespaces, name = eotype.name.split(".")
+ namespaces = [self.escape_keyword(x.lower()) for x in namespaces]
+ is_interface = eotype.type == eotype.type.CLASS
+ k_name = ("I" if is_interface else "") + name
+ return ".".join(namespaces + [k_name])
+
+ def type_convert(self, eotype):
+ if eotype.type == eotype.type.VOID:
+ return "System.IntPtr"
+
+ new_type = self.dicttypes.get(
+ eotype.name, name_helpers.type_managed_name(eotype)
+ )
+ if new_type not in ("Eina.RwSlice", "Eina.Slice") and eotype.base_type:
+ # Stringshare is a special case where its C# type differs if inside or outside
+ # a container:
+ # - Non-contained stringshares are directly converted to strings.
+ # - Contained stringshares are kept as the container parameter as a tag to
+ # marshal the value correctly whem adding/removing items from the container.
+ if eotype.base_type.name == "stringshare":
+ base_type = "Eina.Stringshare"
+ else:
+ base_type = self.dicttypes.get(
+ eotype.base_type.name,
+ name_helpers.type_managed_name(eotype.base_type),
+ )
+ new_type = "{}<{}>".format(new_type, base_type)
+
+ return new_type
+
+ def event_convert(self, event):
+ return "{}Evt".format("".join([i.capitalize() for i in event.name.split(",")]))
+
+ def print_arg(self, eoarg):
+ r = super().print_arg(eoarg)
+ prefix = self.direction_get(eoarg) or None
+
+ return " ".join([prefix, r]) if prefix else r
+
+ def format_name(self, func):
+ names = func.comp.name.split("_")
+
+ if func.type == func.type.METHOD and names[-1] in self.verbs:
+ names.insert(0, names.pop())
+
+ fname = "".join([name.capitalize() for name in names])
+
+ if func.type == func.type.METHOD:
+ fname = self.escape_keyword(fname)
+
+ return fname
+
+
+def GetKey(ext):
+ if ext == ".cs":
+ return EMonoKeys(ext)
+ return EKeys(ext)
diff --git a/src/scripts/testgen/name_helpers.py b/src/scripts/testgen/name_helpers.py
new file mode 100644
index 0000000000..e03ad23a41
--- /dev/null
+++ b/src/scripts/testgen/name_helpers.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+# encoding: utf-8
+
+"""Helper module with naming rules for the C# binding."""
+
+import os
+import sys
+
+# Hackish way of detecting pyolian...
+script_path = os.path.dirname(os.path.realpath(__file__))
+
+if "EFL_DIR" in os.environ:
+ root_path = os.environ["EFL_DIR"]
+else:
+ root_path = os.path.abspath(os.path.join(script_path, "..", "..", ".."))
+
+sys.path.insert(0, os.path.join(root_path, "src", "scripts"))
+
+from pyolian import eolian
+
+
+def remove_underlines(name):
+ """Removes underlines from name"""
+ return name.replace("_", "")
+
+
+def managed_name(name):
+ """Replaces underlines and capitalize first letter of each word"""
+
+ words = name.split("_")
+ return "".join(word[0].upper() + word[1:] for word in words)
+
+
+def managed_namespaces(namespaces):
+ """Converts an eolian list of namespaces into the managed namespace"""
+ return ".".join(remove_underlines(nsp) for nsp in namespaces)
+
+
+def class_managed_name(cls):
+ """Gets the full managed name of the given eolian class"""
+ ret = managed_namespaces(cls.namespaces)
+
+ if ret:
+ ret += "."
+
+ if cls.type in (eolian.Eolian_Class_Type.INTERFACE, eolian.Eolian_Class_Type.MIXIN):
+ ret += "I"
+
+ ret += remove_underlines(cls.short_name)
+
+ if ret == "Efl.Class":
+ return "System.Type"
+
+ return ret
+
+
+def type_managed_name(type):
+ """Gets the full managed name of a given type."""
+ if type.type == eolian.Eolian_Type_Type.CLASS:
+ return class_managed_name(type.class_)
+
+ ret = managed_namespaces(type.namespaces)
+
+ if ret:
+ ret += "."
+
+ ret += remove_underlines(type.short_name)
+
+ return ret
+
+
+# Need to pass the class as it is not accessible from Event in Pyolian
+def event_args_managed_name(event, cls):
+ """Gets the full managed name of the event arguments struct"""
+ if event.type is None:
+ return "System.EventArgs"
+
+ ret = class_managed_name(cls)
+
+ return ret + managed_name(event.myname) + "Evt_Args"
+
+
+def event_managed_short_name(event):
+ """Gets the managed short name of an event"""
+
+ return managed_name(event.name.replace(",", "_")) + "Evt"
+
+
+def enum_field_managed_name(field):
+ """Gets the managed name of an Enum field"""
+
+ return managed_name(field.name)
diff --git a/src/scripts/testgen/suitegen.py b/src/scripts/testgen/suitegen.py
new file mode 100644
index 0000000000..5551eabf8e
--- /dev/null
+++ b/src/scripts/testgen/suitegen.py
@@ -0,0 +1,291 @@
+import itertools
+import os
+from pyolian.eolian import Eolian_Function_Type, Eolian_Class_Type, Eolian_Object_Scope
+from .ekeys import GetKey, Function_List_Type
+from pyolian import eolian
+
+from testgen import name_helpers
+
+
+class BaseItem:
+ def __init__(self, path, keys, prefix=""):
+ self.path = path
+ self.keys = keys
+ self.prefix = prefix
+
+ def __getattr__(self, attr):
+ if not attr.split("_")[-1] in self.keys.keyloads:
+ raise AttributeError("Error getting {}".format(attr))
+
+ filename = os.path.join(self.path, self.prefix + attr) + self.keys.ext
+ if os.path.isfile(filename):
+ with open(filename, "r") as f:
+ return f.read()
+ return None
+
+
+class ComItem(BaseItem):
+ def __init__(self, comp, path, keys):
+ super().__init__(path, keys)
+ self.comp = comp
+
+ def __getattr__(self, attr):
+ if hasattr(self.comp, attr):
+ return getattr(self.comp, attr)
+ return super().__getattr__(attr)
+
+
+class FuncItem(ComItem):
+ def __init__(self, comp, path, keys):
+ super().__init__(comp, os.path.join(path, comp.name), keys)
+
+ self.has_getter = (
+ comp.type in (Eolian_Function_Type.PROP_GET, Eolian_Function_Type.PROPERTY)
+ and comp.full_c_getter_name not in keys.blacklist
+ and comp.getter_scope == Eolian_Object_Scope.PUBLIC
+ and not os.path.isfile("{}_get".format(os.path.join(path, comp.name)))
+ )
+ self.has_setter = (
+ comp.type in (Eolian_Function_Type.PROP_SET, Eolian_Function_Type.PROPERTY)
+ and comp.full_c_setter_name not in keys.blacklist
+ and comp.setter_scope == Eolian_Object_Scope.PUBLIC
+ and not os.path.isfile("{}_set".format(os.path.join(path, comp.name)))
+ )
+
+ self.is_enum = (
+ lambda arg: arg.type
+ and arg.type.typedecl
+ and arg.type.typedecl.type == arg.type.typedecl.type.ENUM
+ )
+ self.is_number = lambda arg: arg.type and arg.type.builtin_type in (
+ arg.type.builtin_type.INT,
+ arg.type.builtin_type.UINT,
+ arg.type.builtin_type.LONG,
+ arg.type.builtin_type.ULONG,
+ arg.type.builtin_type.LLONG,
+ arg.type.builtin_type.ULLONG,
+ arg.type.builtin_type.INT8,
+ arg.type.builtin_type.UINT8,
+ arg.type.builtin_type.INT16,
+ arg.type.builtin_type.UINT16,
+ arg.type.builtin_type.INT32,
+ arg.type.builtin_type.UINT32,
+ arg.type.builtin_type.INT64,
+ arg.type.builtin_type.UINT64,
+ arg.type.builtin_type.INT128,
+ arg.type.builtin_type.UINT128,
+ )
+
+ @property
+ def getter_args(self):
+ return itertools.chain(self.getter_values, self.getter_keys)
+
+ @property
+ def setter_args(self):
+ return itertools.chain(self.setter_values, self.setter_keys)
+
+ @property
+ def format_name(self):
+ return self.keys.format_name(self)
+
+
+class EventItem(ComItem):
+ def __init__(self, comp, path, keys):
+ self.myname = comp.name.replace(",", "_")
+ super().__init__(comp, os.path.join(path, self.myname), keys)
+ self.format_name = self.keys.event_convert(self)
+
+
+class ClassItem(ComItem):
+ def __init__(self, comp, path, keys):
+ self.myname = os.path.splitext(comp.file)[0]
+ super().__init__(comp, os.path.join(path, self.myname), keys)
+
+ def mfilter(f):
+ if f.full_c_method_name in self.keys.blacklist:
+ return False
+
+ if os.path.isfile(os.path.join(self.path, f.name)):
+ return False
+
+ if f.type == Eolian_Function_Type.PROPERTY:
+ if f.getter_scope != Eolian_Object_Scope.PUBLIC:
+ scope = f.setter_scope
+ else:
+ scope = f.getter_scope
+ else:
+ scope = f.scope_get(f.type)
+
+ if scope != Eolian_Object_Scope.PUBLIC:
+ return False
+
+ return True
+
+ if self.keys.funclist & Function_List_Type.OWN:
+ self._methods = {
+ m.name: FuncItem(m, self.path, keys)
+ for m in self.comp.methods
+ if mfilter(m)
+ }
+ self._properties = {
+ p.name: FuncItem(p, self.path, keys)
+ for p in self.comp.properties
+ if mfilter(p)
+ }
+ self._events = {
+ e.name: EventItem(e, self.path, keys) for e in self.comp.events
+ }
+ else:
+ self._methods = {}
+ self._properties = {}
+ self._events = {}
+
+ if self.keys.funclist & Function_List_Type.IMPLEMENTS:
+ for imp in comp.implements:
+
+ if (
+ imp.namespace == self.name
+ or imp.short_name.lower() in self.keys.implementsbl
+ ):
+ continue
+
+ f = imp.function
+
+ if not mfilter(f):
+ continue
+
+ if f.type == Eolian_Function_Type.METHOD:
+ if f.name in self._methods:
+ continue
+ self._methods[f.name] = FuncItem(f, self.path, keys)
+ elif f.type in (
+ Eolian_Function_Type.PROPERTY,
+ Eolian_Function_Type.PROP_GET,
+ Eolian_Function_Type.PROP_SET,
+ ):
+ if f.name in self._properties:
+ continue
+ self._properties[f.name] = FuncItem(f, self.path, keys)
+
+ parents = []
+
+ if self.keys.funclist & Function_List_Type.INHERITS_FULL:
+ # Use inherits full to get inherited interfaces too
+ parents = self.comp.inherits_full
+ else:
+ if self.keys.funclist & Function_List_Type.EXTENSIONS:
+ parents = self.comp.extensions_hierarchy
+
+ if self.keys.funclist & Function_List_Type.INHERITED:
+ if parents:
+ parents = itertools.chain(self.comp.hierarchy, parents)
+ else:
+ parents = self.comp.hierarchy
+
+ for eoclass in parents:
+ for f in filter(mfilter, eoclass.methods):
+ if f.name in self._methods:
+ continue
+ self._methods[f.name] = FuncItem(f, self.path, keys)
+ for f in filter(mfilter, eoclass.properties):
+ if f.name in self._properties:
+ continue
+ self._properties[f.name] = FuncItem(f, self.path, keys)
+
+ @property
+ def properties(self):
+ return filter(lambda p: p.has_setter or p.has_getter, self._properties.values())
+
+ @property
+ def properties_get(self):
+ return filter(lambda p: p.has_getter, self._properties.values())
+
+ @property
+ def properties_set(self):
+ return filter(lambda p: p.has_setter, self._properties.values())
+
+ @property
+ def methods(self):
+ return self._methods.values()
+
+ @property
+ def events(self):
+ return self._events.values()
+
+ def __iter__(self):
+ return itertools.chain(self.methods, self.properties)
+
+
+class SuiteGen(BaseItem):
+ def __init__(self, name, testname, filename, path, template=None):
+ keys = GetKey(os.path.splitext(filename)[1])
+ super().__init__(path, keys, name + "_")
+ self.name = name
+ self.testname = testname
+ self.fullname = "_".join([name, testname]) if testname else name
+ self.filename = filename
+ self.template = template
+ self.clslist = []
+
+ if not self.template:
+ script_path = os.path.dirname(os.path.realpath(__file__))
+ self.template = os.path.join(
+ script_path, "testgenerator{}.template".format(self.keys.ext)
+ )
+
+ def __iter__(self):
+ return iter(self.clslist)
+
+ def type_convert(self, eotype):
+ if eotype.type == eolian.Eolian_Type_Type.CLASS:
+ return name_helpers.class_managed_name(eotype.class_)
+
+ if eotype.typedecl:
+ return name_helpers.type_managed_name(eotype)
+
+ return self.keys.type_convert(eotype)
+
+ def constructor_params(self, cls):
+ ret = []
+
+ constructors = itertools.chain(
+ cls.constructors, *[base.constructors for base in cls.inherits_full]
+ )
+
+ for constructor in constructors:
+ # Skip optional constructors for now
+ if constructor.is_optional:
+ continue
+ func = constructor.function
+
+ if func.type == eolian.Eolian_Function_Type.PROPERTY:
+ first_param = list(func.setter_values)[0]
+ else:
+ first_param = list(func.parameters)[0]
+ param_type = first_param.type
+
+ ret.append("default({})".format(name_helpers.type_managed_name(param_type)))
+
+ return (", " if ret else "") + ", ".join(ret)
+
+ def print_arg(self, eoarg):
+ return self.keys.print_arg(eoarg)
+
+ def intersect(self, a, b):
+ return list(set(a) & set(b))
+
+ def loadFiles(self, eolian_db, eofiles):
+ self.clslist.clear()
+ for eofile in eofiles:
+ eocls = eolian_db.class_by_file_get(os.path.basename(eofile))
+ if not eocls or eocls.type != Eolian_Class_Type.REGULAR:
+ continue
+ self.loadObj(eocls)
+
+ def loadObj(self, eocls):
+ cls = ClassItem(eocls, self.path, self.keys)
+ if not os.path.isfile(cls.path):
+ cls.myfullname = "{}_{}".format(self.fullname, cls.myname)
+ self.clslist.append(cls)
+ else:
+ print("removing {} Class from generated list".format(cls.name))
diff --git a/src/scripts/testgen/testgen.py b/src/scripts/testgen/testgen.py
new file mode 100755
index 0000000000..24ec00195e
--- /dev/null
+++ b/src/scripts/testgen/testgen.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+# encoding: utf-8
+
+import os
+import sys
+import datetime
+
+
+script_path = os.path.dirname(os.path.realpath(__file__))
+
+if "EFL_DIR" in os.environ:
+ root_path = os.environ["EFL_DIR"]
+else:
+ root_path = os.path.abspath(os.path.join(script_path, "..", "..", ".."))
+
+sys.path.insert(0, os.path.join(root_path, "src", "scripts"))
+
+from pyolian import eolian
+from pyolian import pyratemp
+from testgen.suitegen import SuiteGen
+from testgen import name_helpers
+
+# Use .eo files from the source tree (not the installed ones)
+SCAN_FOLDER = os.path.join(root_path, "src", "lib")
+
+# create main eolian state
+eolian_db = eolian.Eolian_State()
+if not isinstance(eolian_db, eolian.Eolian_State):
+ raise (RuntimeError("Eolian, failed to create Eolian state"))
+
+# eolian source tree scan
+if not eolian_db.directory_add(SCAN_FOLDER):
+ raise (RuntimeError("Eolian, failed to scan source directory"))
+
+# Parse all known eo files
+if not eolian_db.all_eot_files_parse():
+ raise (RuntimeError("Eolian, failed to parse all EOT files"))
+
+if not eolian_db.all_eo_files_parse():
+ raise (RuntimeError("Eolian, failed to parse all EO files"))
+
+# cleanup the database on exit
+import atexit
+
+
+def cleanup_db():
+ global eolian_db
+ del eolian_db
+
+
+atexit.register(cleanup_db)
+
+
+class Template(pyratemp.Template):
+ def __init__(
+ self,
+ filename,
+ encoding="utf-8",
+ loader_class=pyratemp.LoaderFile,
+ parser_class=pyratemp.Parser,
+ renderer_class=pyratemp.Renderer,
+ eval_class=pyratemp.EvalPseudoSandbox,
+ ):
+
+ global_ctx = {}
+ global_ctx.update(
+ {
+ # Template info
+ "date": datetime.datetime.now(),
+ "template_file": os.path.basename(filename),
+ }
+ )
+
+ self.template_filename = filename
+ pyratemp.Template.__init__(
+ self,
+ filename=filename,
+ encoding=encoding,
+ data=global_ctx,
+ loader_class=loader_class,
+ parser_class=parser_class,
+ renderer_class=renderer_class,
+ eval_class=eval_class,
+ )
+
+ def render(self, suite, verbose=True):
+ # Build the context for the template
+ ctx = {}
+ ctx["suite"] = suite
+ ctx["name_helpers"] = name_helpers
+ # render with the augmented context
+ output = self(**ctx)
+
+ if suite.filename is not None:
+ # write to file
+ with open(suite.filename, "w") as f:
+ f.write(output)
+
+
+if __name__ == "__main__":
+ import argparse
+
+ parser = argparse.ArgumentParser(description="Eolian Test Generator.")
+ parser.add_argument(
+ "testname",
+ help="The Test Name used to find custom and template files. (REQUIRED)",
+ )
+ parser.add_argument(
+ "suitename", help="The Suite Name used to find custom files. (REQUIRED)"
+ )
+ parser.add_argument("filename", help="Generated test file destination. (REQUIRED)")
+ parser.add_argument("eofiles", nargs="*", help="The Eolian Files to use.")
+
+ args = parser.parse_args()
+
+ testdir = os.path.join(root_path, "src", "tests", args.testname)
+
+ suite = SuiteGen(args.suitename, args.testname, args.filename, testdir)
+ suite.loadFiles(eolian_db, args.eofiles)
+
+ t = Template(suite.template)
+ # try:
+ t.render(suite)
+# except:
+# print("ERROR RENDERING - Cannot create file: {}".format(suite.filename))
diff --git a/src/scripts/testgen/testgenerator.c.template b/src/scripts/testgen/testgenerator.c.template
new file mode 100644
index 0000000000..99fc76d596
--- /dev/null
+++ b/src/scripts/testgen/testgenerator.c.template
@@ -0,0 +1,187 @@
+<!--(macro m_show)-->
+ <!--(if mshow)-->
+${mshow}$#!
+ <!--(end)-->
+<!--(end)-->
+<!--(macro init)-->
+ Eo *parent = NULL;
+ Eo *obj = NULL;
+
+ <!--(if exists("mfunc") and mfunc!= None)-->
+${mfunc}$
+ <!--(elif exists("mcls") and mcls!= None)-->
+${mcls}$
+ <!--(else)-->
+ obj = efl_add_ref(${cls.c_macro}$, parent);
+ fail_if(!obj, "ERROR: Cannot init ${cls.name}$!\n");
+ <!--(end)-->
+<!--(end)-->
+<!--(macro shutdown)-->
+ /** shutdown **/
+ <!--(if exists("mfunc") and mfunc != None)-->
+${mfunc}$
+ <!--(elif exists("mcls") and mcls != None)-->
+${mcls}$
+ <!--(end)-->
+ efl_unref(obj);
+<!--(end)-->
+<!--(macro arg_default)-->
+ <!--(if arg.type.name == "__builtin_free_cb" or arg.type.is_ptr or arg.type.type == arg.type.type.CLASS or arg.type.builtin_type == arg.type.builtin_type.STRING)-->NULL<!--(elif arg.type.builtin_type == arg.type.builtin_type.ANY_VALUE)-->EINA_VALUE_EMPTY<!--(elif arg.type.typedecl and arg.type.typedecl.type == arg.type.typedecl.type.STRUCT )-->{}<!--(else)-->0<!--(end)-->;
+<!--(end)-->
+<!--(macro args_declaration)-->
+ <!--(for arg in args)-->
+ <!--(if arg.type.typedecl and arg.type.typedecl.type == arg.type.typedecl.type.FUNCTION_POINTER)-->
+ void * arg_${arg.name}$_data = NULL;
+ ${arg.type.c_type_param}$ arg_${arg.name}$ = NULL;
+ Eina_Free_Cb arg_${arg.name}$_free_cb = NULL;
+ <!--(else)-->
+ ${arg.type.c_type_param}$ arg_${arg.name}$ = ${arg_default(arg=arg)}$
+ <!--(end)-->
+ <!--(end)-->
+<!--(end)-->
+<!--(macro print_arg)-->
+ <!--(if arg.type.typedecl and arg.type.typedecl.type == arg.type.typedecl.type.FUNCTION_POINTER)-->
+arg_${arg.name}$_data, arg_${arg.name}$, arg_${arg.name}$_free_cb
+ <!--(else)-->
+ <!--(if arg.direction in (arg.direction.OUT, arg.direction.INOUT))-->&<!--(end)-->arg_${arg.name}$
+ <!--(end)-->
+<!--(end)-->
+<!--(macro arg_self)-->
+ <!--(if not func.is_class)-->
+ obj
+ <!--(end)-->
+<!--(end)-->
+<!--(macro print_comma)-->
+ <!--(if i > 0 or not is_class)-->
+ ,
+ <!--(end)-->
+<!--(end)-->
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <check.h>
+#include "efl_check.h"
+${m_show(mshow=suite.custom)}$#!
+#include <Elementary.h>
+
+<!--(for cls in suite)-->
+void ${cls.myfullname}$_test(TCase *tc);
+<!--(end)-->
+
+static const Efl_Test_Case etc[] = {
+<!--(for cls in suite)-->
+ { "${suite.name.capitalize()}$ ${suite.testname.capitalize()}$ ${cls.myname.capitalize()}$", ${cls.myfullname}$_test },
+<!--(end)-->
+ { NULL, NULL }
+};
+
+<!--(for cls in suite)-->
+
+/**************** TEST CASE ${cls.c_macro}$ ****************/
+${m_show(mshow=cls.custom)}$#!
+
+START_TEST(${cls.myfullname}$_smoke)
+{
+${init(mcls=cls.init)}$
+${shutdown(mcls=cls.shutdown)}$
+}
+END_TEST
+
+ <!--(for func in cls.methods)-->
+START_TEST(${cls.myfullname}$_${func.full_c_method_name}$)
+{
+${args_declaration(args=func.parameters)}$${init(mcls=cls.init,mfunc=func.init)}$
+${m_show(mshow=func.arg_init)}$#!
+ <!--(if func.method_return_type)-->${func.method_return_type.c_type_return}$ r = <!--(end)-->${func.full_c_method_name}$(${arg_self(func=func)}$<!--(for i, arg in enumerate(func.parameters))-->${print_comma(i=i, is_class=func.is_class)}$${print_arg(arg=arg)}$<!--(end)-->);
+ <!--(if func.method_return_type)-->(void)r;<!--(end)-->
+${m_show(mshow=func.arg_shutdown)}$#!
+${shutdown(mcls=cls.shutdown,mfunc=func.shutdown)}$
+}
+END_TEST
+
+ <!--(end)-->
+
+ <!--(for func in cls.properties)-->
+ <!--(if func.has_getter)-->
+START_TEST(${cls.myfullname}$_${func.full_c_getter_name}$)
+{
+ <!--(if len(list(func.getter_values)) > 1)-->
+${args_declaration(args=func.getter_values)}$
+ <!--(end)-->
+${args_declaration(args=func.getter_keys)}$${init(mcls=cls.init,mfunc=func.get_init)}$
+${m_show(mshow=func.arg_get_init)}$#!
+ <!--(if len(list(func.getter_values)) == 1)-->
+ ${list(func.getter_values)[0].type.c_type_return}$ r = ${func.full_c_getter_name}$(obj<!--(for arg in func.getter_keys)-->, arg_${arg.name}$<!--(end)-->);
+ (void)r;
+ <!--(else)-->
+ ${func.full_c_getter_name}$(obj<!--(for arg in func.getter_keys)-->, arg_${arg.name}$<!--(end)--><!--(for arg in func.getter_values)-->, &arg_${arg.name}$<!--(end)-->);
+ <!--(end)-->
+${m_show(mshow=func.arg_get_shutdown)}$#!
+${shutdown(mcls=cls.shutdown,mfunc=func.get_shutdown)}$
+}
+END_TEST
+
+ <!--(end)-->
+ <!--(if func.has_setter)-->
+START_TEST(${cls.myfullname}$_${func.full_c_setter_name}$)
+{
+${args_declaration(args=func.setter_keys)}$${args_declaration(args=func.setter_values)}$${init(mcls=cls.init,mfunc=func.set_init)}$
+${m_show(mshow=func.arg_set_init)}$#!
+ ${func.full_c_setter_name}$(obj<!--(for arg in func.setter_keys)-->, arg_${arg.name}$<!--(end)--><!--(for arg in func.setter_values)-->, arg_${arg.name}$<!--(end)-->);
+${m_show(mshow=func.arg_set_shutdown)}$#!
+${shutdown(mcls=cls.shutdown,mfunc=func.set_shutdown)}$
+}
+END_TEST
+
+ <!--(end)-->
+ <!--(end)-->
+void ${cls.myfullname}$_test(TCase *tc)
+{
+ tcase_add_test(tc, ${cls.myfullname}$_smoke);
+ <!--(for func in cls.methods)-->
+ tcase_add_test(tc, ${cls.myfullname}$_${func.full_c_method_name}$);
+ <!--(end)-->
+ <!--(for func in cls.properties_get)-->
+ tcase_add_test(tc, ${cls.myfullname}$_${func.full_c_getter_name}$);
+ <!--(end)-->
+ <!--(for func in cls.properties_set)-->
+ tcase_add_test(tc, ${cls.myfullname}$_${func.full_c_setter_name}$);
+ <!--(end)-->
+}
+<!--(end)-->
+
+SUITE_INIT(${suite.name}$)
+{
+ fail_if(!eina_init(), "ERROR: Cannot init Eina!\n");
+ fail_if(!ecore_init(), "ERROR: Cannot init Ecore!\n");
+ fail_if(!efl_object_init(), "ERROR: Cannot init EO!\n");
+${m_show(mshow=suite.init)}$#!
+}
+
+SUITE_SHUTDOWN(${suite.name}$)
+{
+${m_show(mshow=suite.shutdown)}$#!
+ ecore_shutdown();
+ eina_shutdown();
+}
+
+int
+main(int argc, char **argv)
+{
+ int failed_count;
+
+ if (!_efl_test_option_disp(argc, argv, etc))
+ return 0;
+
+#ifdef NEED_RUN_IN_TREE
+ putenv("EFL_RUN_IN_TREE=1");
+#endif
+
+ failed_count = _efl_suite_build_and_run(argc - 1, (const char **)argv + 1,
+ "${suite.fullname}$", etc, SUITE_INIT_FN(${suite.name}$), SUITE_SHUTDOWN_FN(${suite.name}$));
+
+ return (failed_count == 0) ? 0 : 255;
+}
+
diff --git a/src/scripts/testgen/testgenerator.cs.template b/src/scripts/testgen/testgenerator.cs.template
new file mode 100644
index 0000000000..c2085e838d
--- /dev/null
+++ b/src/scripts/testgen/testgenerator.cs.template
@@ -0,0 +1,113 @@
+<!--(macro m_show)-->
+ <!--(if mshow)-->
+${mshow}$#!
+ <!--(end)-->
+<!--(end)-->
+<!--(macro def_obj)-->${name_helpers.class_managed_name(param.type.class_)}$ arg_${param.name}$ = null;<!--(end)-->
+<!--(macro def_param)-->
+ <!--(if param.type.type == param.type.type.CLASS)-->${def_obj(param=param)}$<!--(else)-->${suite.type_convert(param.type)}$ arg_${param.name}$ = default(${suite.type_convert(param.type)}$);<!--(end)-->
+<!--(end)-->
+<!--(macro def_params)-->
+ <!--(for p in parameters)-->
+ ${def_param(param=p)}$
+ <!--(end)-->
+<!--(end)-->
+<!--(macro meth_target)-->
+ <!--(if func.is_class)-->${name_helpers.class_managed_name(cls)}$<!--(else)-->obj<!--(end)-->
+<!--(end)-->
+using System;
+
+namespace TestSuite
+{
+<!--(if suite.custom)-->${suite.custom}$<!--(end)-->
+<!--(for cls in suite)-->
+/**************** TEST CASE ${cls.c_macro}$ ****************/
+class Test${cls.name.replace('.','')}$
+{
+
+ ${name_helpers.class_managed_name(cls)}$ obj;
+${m_show(mshow=cls.custom)}$#!
+
+ public void SetUp()
+ {
+${m_show(mshow=suite.init)}$#!
+ <!--(if cls.init)-->
+${cls.init}$
+ <!--(else)-->
+ obj = new ${name_helpers.class_managed_name(cls)}$(null${suite.constructor_params(cls)}$);
+ <!--(end)-->
+ }
+
+ public void TearDown()
+ {
+${m_show(mshow=suite.shutdown)}$#!
+ <!--(if cls.shutdown)-->
+${cls.shutdown}$
+ <!--(else)-->
+ obj.Dispose();
+ obj = null;
+ <!--(end)-->
+ }
+
+ public void smoke()
+ {
+ }
+
+#! METHODS
+ <!--(for func in cls.methods)-->
+ public void ${func.name}$()
+ {
+ <!--(if len(list(func.parameters)) > 0)-->
+${def_params(parameters=func.parameters)}$
+ <!--(end)-->
+${m_show(mshow=func.arg_init)}$#!
+${m_show(mshow=func.init)}$#!
+ <!--(if func.method_return_type)-->var r = <!--(end)-->${meth_target(func=func, cls=cls)}$.${func.format_name}$(${', '.join([ suite.print_arg(p) for p in func.parameters])}$);
+${m_show(mshow=func.arg_shutdown)}$#!
+${m_show(mshow=func.shutdown)}$#!
+ }
+
+ <!--(end)-->
+#! PROPERTIES FUNCTION GET
+ <!--(for func in cls.properties)-->
+ <!--(if func.has_getter)-->
+ public void ${func.name}$_pget()
+ {
+ <!--(if func.getter_return_type or len(list(func.getter_values)) > 1)-->
+${def_params(parameters=func.getter_values)}$
+ <!--(end)-->
+ <!--(if len(list(func.getter_keys)) > 0)-->
+${def_params(parameters=func.getter_keys)}$
+ <!--(end)-->
+${m_show(mshow=func.arg_get_init)}$#!
+${m_show(mshow=func.get_init)}$#!
+ <!--(if not func.getter_return_type and len(list(func.getter_values)) == 1)-->
+ var arg_${list(func.getter_values)[0].name}$ = ${meth_target(func=func, cls=cls)}$.Get${func.format_name}$(${', '.join(['arg_{}'.format(param.name) for param in func.getter_keys])}$);
+ <!--(else)-->
+ <!--(if func.getter_return_type)-->var r = <!--(end)-->${meth_target(func=func, cls=cls)}$.Get${func.format_name}$(${', '.join([suite.print_arg(p) for p in func.getter_keys] + ['out arg_{}'.format(p.name) for p in func.getter_values])}$);
+ <!--(end)-->
+${m_show(mshow=func.arg_get_shutdown)}$#!
+${m_show(mshow=func.get_shutdown)}$#!
+ }
+
+ <!--(end)-->
+#! PROPERTIES FUNCTION SET
+ <!--(if func.has_setter)-->
+ public void ${func.name}$_pset()
+ {
+${def_params(parameters=func.setter_values)}$
+ <!--(if len(list(func.setter_keys)) > 0)-->
+${def_params(parameters=func.setter_keys)}$
+ <!--(end)-->
+${m_show(mshow=func.arg_set_init)}$#!
+${m_show(mshow=func.set_init)}$#!
+ ${meth_target(func=func, cls=cls)}$.Set${func.format_name}$(${', '.join([suite.print_arg(p) for p in list(func.setter_keys) + list(func.setter_values)])}$);
+${m_show(mshow=func.arg_set_shutdown)}$#!
+${m_show(mshow=func.set_shutdown)}$#!
+ }
+
+ <!--(end)-->
+ <!--(end)-->
+}
+<!--(end)-->
+}
diff --git a/src/tests/automated/ecore_audio_custom.c b/src/tests/automated/ecore_audio_custom.c
new file mode 100644
index 0000000000..538ed42109
--- /dev/null
+++ b/src/tests/automated/ecore_audio_custom.c
@@ -0,0 +1,3 @@
+#include <Ecore.h>
+#include <Ecore_Audio.h>
+#include <Ecore_File.h>
diff --git a/src/tests/automated/ecore_audio_init.c b/src/tests/automated/ecore_audio_init.c
new file mode 100644
index 0000000000..3dd8aecd65
--- /dev/null
+++ b/src/tests/automated/ecore_audio_init.c
@@ -0,0 +1,2 @@
+ int _rinit = ecore_audio_init();
+ ck_assert_int_eq(_rinit, 1);
diff --git a/src/tests/automated/ecore_audio_out/input_attach/arg_init.c b/src/tests/automated/ecore_audio_out/input_attach/arg_init.c
new file mode 100644
index 0000000000..fcebbe029b
--- /dev/null
+++ b/src/tests/automated/ecore_audio_out/input_attach/arg_init.c
@@ -0,0 +1 @@
+ arg_input = efl_add(ECORE_AUDIO_IN_CLASS, NULL);
diff --git a/src/tests/automated/ecore_audio_out/input_detach/arg_init.c b/src/tests/automated/ecore_audio_out/input_detach/arg_init.c
new file mode 100644
index 0000000000..fcebbe029b
--- /dev/null
+++ b/src/tests/automated/ecore_audio_out/input_detach/arg_init.c
@@ -0,0 +1 @@
+ arg_input = efl_add(ECORE_AUDIO_IN_CLASS, NULL);
diff --git a/src/tests/automated/ecore_audio_out_wasapi/init.c b/src/tests/automated/ecore_audio_out_wasapi/init.c
new file mode 100644
index 0000000000..da9426da1e
--- /dev/null
+++ b/src/tests/automated/ecore_audio_out_wasapi/init.c
@@ -0,0 +1,3 @@
+#ifdef _WIN32
+ obj = efl_add_ref(ECORE_AUDIO_OUT_WASAPI_CLASS, parent);
+ fail_if(!obj, "ERROR: Cannot init Ecore.Audio.Out.Wasapi!\n")
diff --git a/src/tests/automated/ecore_audio_out_wasapi/shutdown.c b/src/tests/automated/ecore_audio_out_wasapi/shutdown.c
new file mode 100644
index 0000000000..23fe0f1229
--- /dev/null
+++ b/src/tests/automated/ecore_audio_out_wasapi/shutdown.c
@@ -0,0 +1,3 @@
+#else
+(void)parent;
+#endif
diff --git a/src/tests/automated/ector_custom.c b/src/tests/automated/ector_custom.c
new file mode 100644
index 0000000000..0ff115b738
--- /dev/null
+++ b/src/tests/automated/ector_custom.c
@@ -0,0 +1,3 @@
+#include <cairo/Ector_Cairo.h>
+#include <software/Ector_Software.h>
+#include <gl/Ector_GL.h>
diff --git a/src/tests/automated/ector_init.c b/src/tests/automated/ector_init.c
new file mode 100644
index 0000000000..b0006b6a1f
--- /dev/null
+++ b/src/tests/automated/ector_init.c
@@ -0,0 +1 @@
+ fail_if(!ector_init(), "ERROR: Cannot init Ector!\n");
diff --git a/src/tests/automated/ector_renderer_cairo_shape/init.c b/src/tests/automated/ector_renderer_cairo_shape/init.c
new file mode 100644
index 0000000000..e0d899fa57
--- /dev/null
+++ b/src/tests/automated/ector_renderer_cairo_shape/init.c
@@ -0,0 +1,2 @@
+Ector_Surface *surface = efl_add(ECTOR_CAIRO_SOFTWARE_SURFACE_CLASS, NULL);
+obj = efl_add_ref(ECTOR_RENDERER_CAIRO_SHAPE_CLASS, parent, ector_renderer_surface_set(efl_added, surface));
diff --git a/src/tests/automated/ector_shutdown.c b/src/tests/automated/ector_shutdown.c
new file mode 100644
index 0000000000..2428e6ec56
--- /dev/null
+++ b/src/tests/automated/ector_shutdown.c
@@ -0,0 +1 @@
+ ector_shutdown();
diff --git a/src/tests/automated/edje_custom.c b/src/tests/automated/edje_custom.c
new file mode 100644
index 0000000000..edbf1b78f2
--- /dev/null
+++ b/src/tests/automated/edje_custom.c
@@ -0,0 +1 @@
+#define EFL_CANVAS_LAYOUT_BETA
diff --git a/src/tests/automated/edje_init.c b/src/tests/automated/edje_init.c
new file mode 100644
index 0000000000..4e81da1772
--- /dev/null
+++ b/src/tests/automated/edje_init.c
@@ -0,0 +1,2 @@
+ fail_if(!ecore_evas_init(), "ERROR: Cannot init Ecore Evas!\n");
+ fail_if(!edje_init(), "ERROR: Cannot init Edje!\n");
diff --git a/src/tests/automated/edje_shutdown.c b/src/tests/automated/edje_shutdown.c
new file mode 100644
index 0000000000..450dda7d2b
--- /dev/null
+++ b/src/tests/automated/edje_shutdown.c
@@ -0,0 +1,2 @@
+ edje_shutdown();
+ ecore_evas_shutdown();
diff --git a/src/tests/automated/efl_canvas_layout_part/init.c b/src/tests/automated/efl_canvas_layout_part/init.c
new file mode 100644
index 0000000000..7d4a56a17b
--- /dev/null
+++ b/src/tests/automated/efl_canvas_layout_part/init.c
@@ -0,0 +1,9 @@
+ parent = evas_new();
+ evas_output_method_set(parent, evas_render_method_lookup("buffer"));
+ Evas_Engine_Info *einfo = evas_engine_info_get(parent);
+ evas_engine_info_set(parent, einfo);
+
+ evas_output_size_set(parent, 500, 500);
+ evas_output_viewport_set(parent, 0, 0, 500, 500);
+
+ (void)obj;
diff --git a/src/tests/automated/efl_canvas_layout_part_box/init.c b/src/tests/automated/efl_canvas_layout_part_box/init.c
new file mode 100644
index 0000000000..7d4a56a17b
--- /dev/null
+++ b/src/tests/automated/efl_canvas_layout_part_box/init.c
@@ -0,0 +1,9 @@
+ parent = evas_new();
+ evas_output_method_set(parent, evas_render_method_lookup("buffer"));
+ Evas_Engine_Info *einfo = evas_engine_info_get(parent);
+ evas_engine_info_set(parent, einfo);
+
+ evas_output_size_set(parent, 500, 500);
+ evas_output_viewport_set(parent, 0, 0, 500, 500);
+
+ (void)obj;
diff --git a/src/tests/automated/efl_canvas_layout_part_external/init.c b/src/tests/automated/efl_canvas_layout_part_external/init.c
new file mode 100644
index 0000000000..b42f732b75
--- /dev/null
+++ b/src/tests/automated/efl_canvas_layout_part_external/init.c
@@ -0,0 +1,8 @@
+ parent = evas_new();
+ evas_output_method_set(parent, evas_render_method_lookup("buffer"));
+ Evas_Engine_Info *einfo = evas_engine_info_get(parent);
+ evas_engine_info_set(parent, einfo);
+
+ evas_output_size_set(parent, 500, 500);
+ evas_output_viewport_set(parent, 0, 0, 500, 500);
+ (void)obj;
diff --git a/src/tests/automated/efl_canvas_layout_part_swallow/init.c b/src/tests/automated/efl_canvas_layout_part_swallow/init.c
new file mode 100644
index 0000000000..b42f732b75
--- /dev/null
+++ b/src/tests/automated/efl_canvas_layout_part_swallow/init.c
@@ -0,0 +1,8 @@
+ parent = evas_new();
+ evas_output_method_set(parent, evas_render_method_lookup("buffer"));
+ Evas_Engine_Info *einfo = evas_engine_info_get(parent);
+ evas_engine_info_set(parent, einfo);
+
+ evas_output_size_set(parent, 500, 500);
+ evas_output_viewport_set(parent, 0, 0, 500, 500);
+ (void)obj;
diff --git a/src/tests/automated/efl_canvas_layout_part_table/init.c b/src/tests/automated/efl_canvas_layout_part_table/init.c
new file mode 100644
index 0000000000..b42f732b75
--- /dev/null
+++ b/src/tests/automated/efl_canvas_layout_part_table/init.c
@@ -0,0 +1,8 @@
+ parent = evas_new();
+ evas_output_method_set(parent, evas_render_method_lookup("buffer"));
+ Evas_Engine_Info *einfo = evas_engine_info_get(parent);
+ evas_engine_info_set(parent, einfo);
+
+ evas_output_size_set(parent, 500, 500);
+ evas_output_viewport_set(parent, 0, 0, 500, 500);
+ (void)obj;
diff --git a/src/tests/automated/efl_canvas_layout_part_text/init.c b/src/tests/automated/efl_canvas_layout_part_text/init.c
new file mode 100644
index 0000000000..b42f732b75
--- /dev/null
+++ b/src/tests/automated/efl_canvas_layout_part_text/init.c
@@ -0,0 +1,8 @@
+ parent = evas_new();
+ evas_output_method_set(parent, evas_render_method_lookup("buffer"));
+ Evas_Engine_Info *einfo = evas_engine_info_get(parent);
+ evas_engine_info_set(parent, einfo);
+
+ evas_output_size_set(parent, 500, 500);
+ evas_output_viewport_set(parent, 0, 0, 500, 500);
+ (void)obj;
diff --git a/src/tests/automated/efl_canvas_video/init.c b/src/tests/automated/efl_canvas_video/init.c
new file mode 100644
index 0000000000..f75bda251f
--- /dev/null
+++ b/src/tests/automated/efl_canvas_video/init.c
@@ -0,0 +1,2 @@
+ obj = efl_add(EFL_CANVAS_VIDEO_CLASS, parent, efl_canvas_object_legacy_ctor(efl_added));
+ fail_if(!obj, "Error: Canot get obj!\n");
diff --git a/src/tests/automated/efl_loop/begin/init.c b/src/tests/automated/efl_loop/begin/init.c
new file mode 100644
index 0000000000..78fbba3fca
--- /dev/null
+++ b/src/tests/automated/efl_loop/begin/init.c
@@ -0,0 +1,9 @@
+int argc = 2;
+char *argv[] = { "efl_ui_suite", "test" };
+(void)parent;
+
+_EFL_APP_VERSION_SET();
+obj = efl_app_get();
+efl_event_callback_add(obj, EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL);
+fail_if(!ecore_init_ex(argc, argv));
+__EFL_MAIN_CONSTRUCTOR;
diff --git a/src/tests/automated/efl_loop/begin/shutdown.c b/src/tests/automated/efl_loop/begin/shutdown.c
new file mode 100644
index 0000000000..1f578789d4
--- /dev/null
+++ b/src/tests/automated/efl_loop/begin/shutdown.c
@@ -0,0 +1,3 @@
+efl_loop_exit_code_process(r);
+__EFL_MAIN_DESTRUCTOR;
+ecore_shutdown_ex();
diff --git a/src/tests/automated/efl_loop/custom.c b/src/tests/automated/efl_loop/custom.c
new file mode 100644
index 0000000000..f7df130584
--- /dev/null
+++ b/src/tests/automated/efl_loop/custom.c
@@ -0,0 +1,5 @@
+EAPI_MAIN void
+efl_main(void *data EINA_UNUSED, const Efl_Event *ev)
+{
+ efl_loop_quit(ev->object, EINA_VALUE_EMPTY);
+}
diff --git a/src/tests/automated/efl_loop/timeout/arg_init.c b/src/tests/automated/efl_loop/timeout/arg_init.c
new file mode 100644
index 0000000000..e2e28fb725
--- /dev/null
+++ b/src/tests/automated/efl_loop/timeout/arg_init.c
@@ -0,0 +1 @@
+ arg_time = 0.5;
diff --git a/src/tests/automated/efl_text_markup_util/init.c b/src/tests/automated/efl_text_markup_util/init.c
new file mode 100644
index 0000000000..4d5230d0b1
--- /dev/null
+++ b/src/tests/automated/efl_text_markup_util/init.c
@@ -0,0 +1 @@
+(void)parent;
diff --git a/src/tests/automated/eio_custom.c b/src/tests/automated/eio_custom.c
new file mode 100644
index 0000000000..7f57ce11c4
--- /dev/null
+++ b/src/tests/automated/eio_custom.c
@@ -0,0 +1 @@
+#include <Eio.h>
diff --git a/src/tests/automated/eio_init.c b/src/tests/automated/eio_init.c
new file mode 100644
index 0000000000..2787098b73
--- /dev/null
+++ b/src/tests/automated/eio_init.c
@@ -0,0 +1 @@
+ fail_if(!eio_init(), "ERROR: Cannot init Eio!\n");
diff --git a/src/tests/automated/eio_shutdown.c b/src/tests/automated/eio_shutdown.c
new file mode 100644
index 0000000000..fad342e9ce
--- /dev/null
+++ b/src/tests/automated/eio_shutdown.c
@@ -0,0 +1 @@
+ eio_shutdown();
diff --git a/src/tests/automated/eldbus_init.c b/src/tests/automated/eldbus_init.c
new file mode 100644
index 0000000000..dcfbbec39e
--- /dev/null
+++ b/src/tests/automated/eldbus_init.c
@@ -0,0 +1 @@
+fail_if(eldbus_init() < 0, "ERROR: Cannot init Eldbus!\n");
diff --git a/src/tests/automated/eldbus_shutdown.c b/src/tests/automated/eldbus_shutdown.c
new file mode 100644
index 0000000000..f3077072c5
--- /dev/null
+++ b/src/tests/automated/eldbus_shutdown.c
@@ -0,0 +1 @@
+eldbus_shutdown();
diff --git a/src/tests/automated/emotion_custom.c b/src/tests/automated/emotion_custom.c
new file mode 100644
index 0000000000..811c9944a8
--- /dev/null
+++ b/src/tests/automated/emotion_custom.c
@@ -0,0 +1,2 @@
+#include "Emotion.h"
+#include "Evas_Internal.h"
diff --git a/src/tests/automated/emotion_init.c b/src/tests/automated/emotion_init.c
new file mode 100644
index 0000000000..f6d1d030a8
--- /dev/null
+++ b/src/tests/automated/emotion_init.c
@@ -0,0 +1,3 @@
+ fail_if(!ecore_evas_init(), "ERROR: Cannot init ECore Evas!\n");
+ fail_if(!emotion_init(), "ERROR: Cannot init Emotion!\n");
+
diff --git a/src/tests/automated/emotion_shutdown.c b/src/tests/automated/emotion_shutdown.c
new file mode 100644
index 0000000000..e82aef7387
--- /dev/null
+++ b/src/tests/automated/emotion_shutdown.c
@@ -0,0 +1,4 @@
+// efl_unref(parent);
+// ecore_evas_free(ee);
+ emotion_shutdown();
+// ecore_evas_shutdown();
diff --git a/src/tests/automated/evas_custom.c b/src/tests/automated/evas_custom.c
new file mode 100644
index 0000000000..6cd14a5113
--- /dev/null
+++ b/src/tests/automated/evas_custom.c
@@ -0,0 +1 @@
+#include "efl_canvas_surface.h"