aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-09-16 10:57:48 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-09-16 10:57:48 +0000
commit785f2a6b3a70454ecfe94addc6480ebf20c44c13 (patch)
tree17a195d2c1f022cd480fd0e0b95be5035ad915e2 /src/tests
parentdfc0331373c3f98df7cb996abc588c7dcf44af0a (diff)
downloadefl-785f2a6b3a70454ecfe94addc6480ebf20c44c13.tar.gz
efl-785f2a6b3a70454ecfe94addc6480ebf20c44c13.tar.xz
efl-785f2a6b3a70454ecfe94addc6480ebf20c44c13.zip
merge : add eina
currently, examples, tests and benchmark are not set. That's the next things i'll do SVN revision: 76710
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/eina/Ecore_Data.h557
-rw-r--r--src/tests/eina/Evas_Data.h195
-rw-r--r--src/tests/eina/Makefile.am142
-rw-r--r--src/tests/eina/city.cc307
-rw-r--r--src/tests/eina/city.h96
-rw-r--r--src/tests/eina/cxx_compile_test.cxx34
-rw-r--r--src/tests/eina/ecore_hash.c949
-rw-r--r--src/tests/eina/ecore_list.c2162
-rw-r--r--src/tests/eina/ecore_sheap.c467
-rw-r--r--src/tests/eina/ecore_strings.c160
-rw-r--r--src/tests/eina/eina_bench.c104
-rw-r--r--src/tests/eina/eina_bench.h36
-rw-r--r--src/tests/eina/eina_bench_array.c699
-rw-r--r--src/tests/eina/eina_bench_convert.c183
-rw-r--r--src/tests/eina/eina_bench_hash.c547
-rw-r--r--src/tests/eina/eina_bench_mempool.c188
-rw-r--r--src/tests/eina/eina_bench_quad.c320
-rw-r--r--src/tests/eina/eina_bench_rectangle_pool.c76
-rw-r--r--src/tests/eina/eina_bench_sort.c222
-rw-r--r--src/tests/eina/eina_bench_stringshare.c185
-rw-r--r--src/tests/eina/eina_bench_stringshare_e17.c118
-rw-r--r--src/tests/eina/eina_suite.c183
-rw-r--r--src/tests/eina/eina_suite.h61
-rw-r--r--src/tests/eina/eina_test_accessor.c243
-rw-r--r--src/tests/eina/eina_test_array.c191
-rw-r--r--src/tests/eina/eina_test_benchmark.c76
-rw-r--r--src/tests/eina/eina_test_binbuf.c263
-rw-r--r--src/tests/eina/eina_test_binshare.c199
-rw-r--r--src/tests/eina/eina_test_clist.c89
-rw-r--r--src/tests/eina/eina_test_convert.c165
-rw-r--r--src/tests/eina/eina_test_counter.c198
-rw-r--r--src/tests/eina/eina_test_error.c243
-rw-r--r--src/tests/eina/eina_test_file.c142
-rw-r--r--src/tests/eina/eina_test_fp.c93
-rw-r--r--src/tests/eina/eina_test_hash.c206
-rw-r--r--src/tests/eina/eina_test_inarray.c401
-rw-r--r--src/tests/eina/eina_test_inlist.c421
-rw-r--r--src/tests/eina/eina_test_iterator.c465
-rw-r--r--src/tests/eina/eina_test_lalloc.c89
-rw-r--r--src/tests/eina/eina_test_list.c385
-rw-r--r--src/tests/eina/eina_test_log.c424
-rw-r--r--src/tests/eina/eina_test_magic.c206
-rw-r--r--src/tests/eina/eina_test_main.c62
-rw-r--r--src/tests/eina/eina_test_matrixsparse.c489
-rw-r--r--src/tests/eina/eina_test_mempool.c187
-rw-r--r--src/tests/eina/eina_test_model.c1288
-rw-r--r--src/tests/eina/eina_test_module.c70
-rw-r--r--src/tests/eina/eina_test_module_dummy.c22
-rw-r--r--src/tests/eina/eina_test_quadtree.c195
-rw-r--r--src/tests/eina/eina_test_rbtree.c452
-rw-r--r--src/tests/eina/eina_test_rectangle.c115
-rw-r--r--src/tests/eina/eina_test_sched.c85
-rw-r--r--src/tests/eina/eina_test_simple_xml_parser.c75
-rw-r--r--src/tests/eina/eina_test_str.c187
-rw-r--r--src/tests/eina/eina_test_strbuf.c449
-rw-r--r--src/tests/eina/eina_test_stringshare.c201
-rw-r--r--src/tests/eina/eina_test_tiler.c184
-rw-r--r--src/tests/eina/eina_test_ustr.c593
-rw-r--r--src/tests/eina/eina_test_ustringshare.c119
-rw-r--r--src/tests/eina/eina_test_value.c1877
-rw-r--r--src/tests/eina/evas_hash.c536
-rw-r--r--src/tests/eina/evas_list.c1093
-rw-r--r--src/tests/eina/evas_mempool.c200
-rw-r--r--src/tests/eina/evas_mempool.h21
-rw-r--r--src/tests/eina/evas_object_list.c183
-rw-r--r--src/tests/eina/evas_stringshare.c275
-rw-r--r--src/tests/eina/sample.gpx26
-rw-r--r--src/tests/eina/strlog46999
68 files changed, 68473 insertions, 0 deletions
diff --git a/src/tests/eina/Ecore_Data.h b/src/tests/eina/Ecore_Data.h
new file mode 100644
index 000000000..50d42f1fe
--- /dev/null
+++ b/src/tests/eina/Ecore_Data.h
@@ -0,0 +1,557 @@
+#ifndef _ECORE_DATA_H
+# define _ECORE_DATA_H
+
+#include <stdio.h>
+/* we need this for size_t */
+#include <stddef.h>
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_BUILD
+# ifdef DLL_EXPORT
+# define EAPI __declspec(dllexport)
+# else
+# define EAPI
+# endif /* ! DLL_EXPORT */
+# else
+# define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUILD */
+#else
+# ifdef __GNUC__
+# if __GNUC__ >= 4
+# define EAPI __attribute__ ((visibility("default")))
+# else
+# define EAPI
+# endif
+# else
+# define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @file Ecore_Data.h
+ * @brief Contains threading, list, hash, debugging and tree functions.
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifdef FREE
+# undef FREE
+#endif
+#define FREE(ptr) free(ptr); ptr = NULL;
+
+#ifdef IF_FREE
+# undef IF_FREE
+#endif
+#define IF_FREE(ptr) if (ptr) {free(ptr); } ptr = NULL;
+
+/* convenience macros for checking pointer parameters for non-NULL */
+#undef CHECK_PARAM_POINTER_RETURN
+#define CHECK_PARAM_POINTER_RETURN(sparam, param, ret) \
+ if (!(param)) \
+ { \
+ printf("***** Developer Warning ***** :\n" \
+ "\tThis program is calling:\n\n" \
+ "\t%s();\n\n" \
+ "\tWith the parameter:\n\n" \
+ "\t%s\n\n" \
+ "\tbeing NULL. Please fix your program.", __FUNCTION__, sparam); \
+ if (getenv("ECORE_ERROR_ABORT")) { abort(); } \
+ return ret; \
+ }
+
+#undef CHECK_PARAM_POINTER
+#define CHECK_PARAM_POINTER(sparam, param) \
+ if (!(param)) \
+ { \
+ printf("***** Developer Warning ***** :\n" \
+ "\tThis program is calling:\n\n" \
+ "\t%s();\n\n" \
+ "\tWith the parameter:\n\n" \
+ "\t%s\n\n" \
+ "\tbeing NULL. Please fix your program.", __FUNCTION__, sparam); \
+ if (getenv("ECORE_ERROR_ABORT")) { abort(); } \
+ return; \
+ }
+
+
+# ifdef __sgi
+# define __FUNCTION__ "unknown"
+# ifndef __cplusplus
+# define inline
+# endif
+# endif
+
+# define ECORE_SORT_MIN 0
+# define ECORE_SORT_MAX 1
+
+typedef void (*Ecore_For_Each)(void *value, void *user_data);
+# define ECORE_FOR_EACH(function) ((Ecore_For_Each)function)
+
+typedef void (*Ecore_Free_Cb)(void *data);
+# define ECORE_FREE_CB(func) ((Ecore_Free_Cb)func)
+
+typedef unsigned int (*Ecore_Hash_Cb)(const void *key);
+# define ECORE_HASH_CB(function) ((Ecore_Hash_Cb)function)
+
+typedef int (*Ecore_Compare_Cb)(const void *data1, const void *data2);
+# define ECORE_COMPARE_CB(function) ((Ecore_Compare_Cb)function)
+
+typedef struct _ecore_list Ecore_List;
+# define ECORE_LIST(list) ((Ecore_List *)list)
+
+typedef struct _ecore_list_node Ecore_List_Node;
+# define ECORE_LIST_NODE(node) ((Ecore_List_Node *)node)
+
+typedef struct _ecore_strbuf Ecore_Strbuf;
+# define ECORE_STRBUF(buf) ((Ecore_Strbuf *)buf)
+
+struct _ecore_list_node
+{
+ void *data;
+ struct _ecore_list_node *next;
+};
+
+struct _ecore_list
+{
+ Ecore_List_Node *first; /* The first node in the list */
+ Ecore_List_Node *last; /* The last node in the list */
+ Ecore_List_Node *current; /* The current node in the list */
+
+ Ecore_Free_Cb free_func; /* The callback to free data in nodes */
+
+ int nodes; /* The number of nodes in the list */
+ int index; /* The position from the front of the
+ list of current node */
+};
+
+EAPI int ecore_direct_compare(const void *key1, const void *key2);
+EAPI int ecore_str_compare(const void *key1, const void *key2);
+
+EAPI unsigned int ecore_direct_hash(const void *key);
+EAPI unsigned int ecore_str_hash(const void *key);
+
+/* Creating and initializing new list structures */
+EAPI Ecore_List * ecore_list_new(void);
+EAPI int ecore_list_init(Ecore_List *list);
+
+/* Adding items to the list */
+EAPI int ecore_list_append(Ecore_List *list, void *_data);
+EAPI int ecore_list_prepend(Ecore_List *list, void *_data);
+EAPI int ecore_list_insert(Ecore_List *list, void *_data);
+EAPI int ecore_list_append_list(Ecore_List *list,
+ Ecore_List *append);
+EAPI int ecore_list_prepend_list(Ecore_List *list,
+ Ecore_List *prepend);
+
+/* Removing items from the list */
+EAPI int ecore_list_remove_destroy(Ecore_List *list);
+EAPI void * ecore_list_remove(Ecore_List *list);
+EAPI void * ecore_list_first_remove(Ecore_List *list);
+EAPI void * ecore_list_last_remove(Ecore_List *list);
+
+/* Retrieve the current position in the list */
+EAPI void * ecore_list_current(Ecore_List *list);
+EAPI void * ecore_list_first(Ecore_List *list);
+EAPI void * ecore_list_last(Ecore_List *list);
+EAPI int ecore_list_index(Ecore_List *list);
+EAPI int ecore_list_count(Ecore_List *list);
+
+/* Traversing the list */
+EAPI int ecore_list_for_each(Ecore_List *list,
+ Ecore_For_Each function,
+ void *user_data);
+EAPI void * ecore_list_first_goto(Ecore_List *list);
+EAPI void * ecore_list_last_goto(Ecore_List *list);
+EAPI void * ecore_list_index_goto(Ecore_List *list, int index);
+EAPI void * ecore_list_goto(Ecore_List *list, const void *_data);
+
+/* Traversing the list and returning data */
+EAPI void * ecore_list_next(Ecore_List *list);
+EAPI void * ecore_list_find(Ecore_List *list,
+ Ecore_Compare_Cb function,
+ const void *user_data);
+
+/* Sorting the list */
+EAPI int ecore_list_sort(Ecore_List *list,
+ Ecore_Compare_Cb compare,
+ char order);
+EAPI int ecore_list_mergesort(Ecore_List *list,
+ Ecore_Compare_Cb compare,
+ char order);
+EAPI int ecore_list_heapsort(Ecore_List *list,
+ Ecore_Compare_Cb compare,
+ char order);
+EAPI void ecore_list_merge(Ecore_List *list, Ecore_List *l2,
+ Ecore_Compare_Cb, char order);
+
+/* Check to see if there is any data in the list */
+EAPI int ecore_list_empty_is(Ecore_List *list);
+
+/* Remove every node in the list without freeing the list itself */
+EAPI int ecore_list_clear(Ecore_List *list);
+/* Free the list and it's contents */
+EAPI void ecore_list_destroy(Ecore_List *list);
+
+/* Creating and initializing list nodes */
+EAPI Ecore_List_Node *ecore_list_node_new(void);
+EAPI int ecore_list_node_init(Ecore_List_Node *newNode);
+
+/* Destroying nodes */
+EAPI int ecore_list_node_destroy(Ecore_List_Node *_e_node,
+ Ecore_Free_Cb free_func);
+
+EAPI int ecore_list_free_cb_set(Ecore_List *list,
+ Ecore_Free_Cb free_func);
+
+typedef Ecore_List Ecore_DList;
+# define ECORE_DLIST(dlist) ((Ecore_DList *)dlist)
+
+typedef struct _ecore_dlist_node Ecore_DList_Node;
+# define ECORE_DLIST_NODE(dlist) ((Ecore_DList_Node *)dlist)
+
+struct _ecore_dlist_node
+{
+ Ecore_List_Node single;
+ Ecore_DList_Node *previous;
+};
+
+/* Creating and initializing new list structures */
+EAPI Ecore_DList *ecore_dlist_new(void);
+EAPI int ecore_dlist_init(Ecore_DList *list);
+EAPI void ecore_dlist_destroy(Ecore_DList *list);
+
+/* Adding items to the list */
+EAPI int ecore_dlist_append(Ecore_DList *_e_dlist, void *_data);
+EAPI int ecore_dlist_prepend(Ecore_DList *_e_dlist, void *_data);
+EAPI int ecore_dlist_insert(Ecore_DList *_e_dlist, void *_data);
+EAPI int ecore_dlist_append_list(Ecore_DList *_e_dlist,
+ Ecore_DList *append);
+EAPI int ecore_dlist_prepend_list(Ecore_DList *_e_dlist,
+ Ecore_DList *prepend);
+
+/* Info about list's state */
+# define ecore_dlist_first(list) ecore_list_first(list)
+# define ecore_dlist_last(list) ecore_list_last(list)
+EAPI void * ecore_dlist_current(Ecore_DList *list);
+EAPI int ecore_dlist_index(Ecore_DList *list);
+# define ecore_dlist_count(list) ecore_list_count(list)
+
+/* Removing items from the list */
+EAPI void * ecore_dlist_remove(Ecore_DList *_e_dlist);
+EAPI void * ecore_dlist_first_remove(Ecore_DList *_e_dlist);
+EAPI int ecore_dlist_remove_destroy(Ecore_DList *list);
+EAPI void * ecore_dlist_last_remove(Ecore_DList *_e_dlist);
+
+/* Traversing the list */
+# define ecore_dlist_for_each(list, function, user_data) \
+ ecore_list_for_each(list, function, user_data)
+EAPI void * ecore_dlist_first_goto(Ecore_DList *_e_dlist);
+EAPI void * ecore_dlist_last_goto(Ecore_DList *_e_dlist);
+EAPI void * ecore_dlist_index_goto(Ecore_DList *_e_dlist, int index);
+EAPI void * ecore_dlist_goto(Ecore_DList *_e_dlist, void *_data);
+
+/* Traversing the list and returning data */
+EAPI void * ecore_dlist_next(Ecore_DList *list);
+EAPI void * ecore_dlist_previous(Ecore_DList *list);
+
+/* Sorting the list */
+EAPI int ecore_dlist_sort(Ecore_DList *list,
+ Ecore_Compare_Cb compare,
+ char order);
+EAPI int ecore_dlist_mergesort(Ecore_DList *list,
+ Ecore_Compare_Cb compare,
+ char order);
+# define ecore_dlist_heapsort(list, compare, order) \
+ ecore_list_heapsort(list, compare, order)
+EAPI void ecore_dlist_merge(Ecore_DList *list, Ecore_DList *l2,
+ Ecore_Compare_Cb, char order);
+
+/* Check to see if there is any data in the list */
+EAPI int ecore_dlist_empty_is(Ecore_DList *_e_dlist);
+
+/* Remove every node in the list without free'ing it */
+EAPI int ecore_dlist_clear(Ecore_DList *_e_dlist);
+
+/* Creating and initializing list nodes */
+EAPI int ecore_dlist_node_init(Ecore_DList_Node *node);
+EAPI Ecore_DList_Node *ecore_dlist_node_new(void);
+
+/* Destroying nodes */
+EAPI int ecore_dlist_node_destroy(Ecore_DList_Node *node,
+ Ecore_Free_Cb free_func);
+
+EAPI int ecore_dlist_free_cb_set(Ecore_DList *dlist,
+ Ecore_Free_Cb free_func);
+
+
+
+/*
+ * Hash Table Implementation:
+ *
+ * Traditional hash table implementation. I had tried a list of tables
+ * approach to save on the realloc's but it ended up being much slower than
+ * the traditional approach.
+ */
+
+typedef struct _ecore_hash_node Ecore_Hash_Node;
+# define ECORE_HASH_NODE(hash) ((Ecore_Hash_Node *)hash)
+
+struct _ecore_hash_node
+{
+ Ecore_Hash_Node *next; /* Pointer to the next node in the bucket list */
+ void *key; /* The key for the data node */
+ void *value; /* The value associated with this node */
+};
+
+typedef struct _ecore_hash Ecore_Hash;
+# define ECORE_HASH(hash) ((Ecore_Hash *)hash)
+
+struct _ecore_hash
+{
+ Ecore_Hash_Node **buckets;
+ int size; /* An index into the table of primes to
+ determine size */
+ int nodes; /* The number of nodes currently in the hash */
+
+ int index; /* The current index into the bucket table */
+
+ Ecore_Compare_Cb compare; /* The function used to compare node values */
+ Ecore_Hash_Cb hash_func; /* The callback function to determine hash */
+
+ Ecore_Free_Cb free_key; /* The callback function to free key */
+ Ecore_Free_Cb free_value; /* The callback function to free value */
+};
+
+/* Create and initialize a hash */
+EAPI Ecore_Hash *ecore_hash_new(Ecore_Hash_Cb hash_func,
+ Ecore_Compare_Cb compare);
+EAPI int ecore_hash_init(Ecore_Hash *hash,
+ Ecore_Hash_Cb hash_func,
+ Ecore_Compare_Cb compare);
+
+/* Functions related to freeing the data in the hash table */
+EAPI int ecore_hash_free_key_cb_set(Ecore_Hash *hash,
+ Ecore_Free_Cb function);
+EAPI int ecore_hash_free_value_cb_set(Ecore_Hash *hash,
+ Ecore_Free_Cb function);
+EAPI void ecore_hash_destroy(Ecore_Hash *hash);
+
+EAPI int ecore_hash_count(Ecore_Hash *hash);
+EAPI int ecore_hash_for_each_node(Ecore_Hash *hash,
+ Ecore_For_Each for_each_func,
+ void *user_data);
+EAPI Ecore_List *ecore_hash_keys(Ecore_Hash *hash);
+
+/* Retrieve and store data into the hash */
+EAPI void * ecore_hash_get(Ecore_Hash *hash, const void *key);
+EAPI int ecore_hash_set(Ecore_Hash *hash, void *key, void *value);
+EAPI int ecore_hash_hash_set(Ecore_Hash *hash, Ecore_Hash *set);
+EAPI void * ecore_hash_remove(Ecore_Hash *hash, const void *key);
+EAPI void * ecore_hash_find(Ecore_Hash *hash,
+ Ecore_Compare_Cb compare,
+ const void *value);
+EAPI void ecore_hash_dump_graph(Ecore_Hash *hash);
+EAPI void ecore_hash_dump_stats(Ecore_Hash *hash);
+
+
+typedef struct _ecore_heap Ecore_Sheap;
+# define ECORE_HEAP(heap) ((Ecore_Sheap *)heap)
+
+struct _ecore_heap
+{
+ void **data;
+ int size;
+ int space;
+
+ char order, sorted;
+
+ /* Callback for comparing node values, default is direct comparison */
+ Ecore_Compare_Cb compare;
+
+ /* Callback for freeing node data, default is NULL */
+ Ecore_Free_Cb free_func;
+};
+
+EAPI Ecore_Sheap *ecore_sheap_new(Ecore_Compare_Cb compare, int size);
+EAPI void ecore_sheap_destroy(Ecore_Sheap *heap);
+EAPI int ecore_sheap_init(Ecore_Sheap *heap,
+ Ecore_Compare_Cb compare,
+ int size);
+EAPI int ecore_sheap_free_cb_set(Ecore_Sheap *heap,
+ Ecore_Free_Cb free_func);
+EAPI int ecore_sheap_insert(Ecore_Sheap *heap, void *data);
+EAPI void * ecore_sheap_extract(Ecore_Sheap *heap);
+EAPI void * ecore_sheap_extreme(Ecore_Sheap *heap);
+EAPI int ecore_sheap_change(Ecore_Sheap *heap,
+ void *item,
+ void *newval);
+EAPI int ecore_sheap_compare_set(Ecore_Sheap *heap,
+ Ecore_Compare_Cb compare);
+EAPI void ecore_sheap_order_set(Ecore_Sheap *heap, char order);
+EAPI void ecore_sheap_sort(Ecore_Sheap *heap);
+
+EAPI void * ecore_sheap_item(Ecore_Sheap *heap, int i);
+
+
+typedef struct _ecore_string Ecore_String;
+struct _ecore_string
+{
+ char *string;
+ int references;
+};
+
+EAPI int ecore_string_init();
+EAPI void ecore_string_shutdown();
+EAPI const char *ecore_string_instance(const char *string);
+EAPI void ecore_string_release(const char *string);
+
+typedef struct _Ecore_Tree_Node Ecore_Tree_Node;
+# define ECORE_TREE_NODE(object) ((Ecore_Tree_Node *)object)
+struct _Ecore_Tree_Node
+{
+
+ /* The actual data for each node */
+ void *key;
+ void *value;
+
+ /* Pointers to surrounding nodes */
+ Ecore_Tree_Node *parent;
+ Ecore_Tree_Node *left_child;
+ Ecore_Tree_Node *right_child;
+
+ /* Book keeping information for quicker balancing of the tree */
+ int max_right;
+ int max_left;
+};
+
+typedef struct _Ecore_Tree Ecore_Tree;
+# define ECORE_TREE(object) ((Ecore_Tree *)object)
+struct _Ecore_Tree
+{
+ /* Nodes of the tree */
+ Ecore_Tree_Node *tree;
+
+ /* Callback for comparing node values, default is direct comparison */
+ Ecore_Compare_Cb compare_func;
+
+ /* Callback for freeing node data, default is NULL */
+ Ecore_Free_Cb free_value;
+ /* Callback for freeing node key, default is NULL */
+ Ecore_Free_Cb free_key;
+};
+
+/* Some basic tree functions */
+/* Allocate and initialize a new tree */
+EAPI Ecore_Tree * ecore_tree_new(Ecore_Compare_Cb compare_func);
+/* Initialize a new tree */
+EAPI int ecore_tree_init(Ecore_Tree *tree,
+ Ecore_Compare_Cb compare_func);
+
+/* Free the tree */
+EAPI int ecore_tree_destroy(Ecore_Tree *tree);
+/* Check to see if the tree has any nodes in it */
+EAPI int ecore_tree_empty_is(Ecore_Tree *tree);
+
+/* Retrieve the value associated with key */
+EAPI void * ecore_tree_get(Ecore_Tree *tree, const void *key);
+EAPI Ecore_Tree_Node *ecore_tree_get_node(Ecore_Tree *tree, const void *key);
+/* Retrieve the value of node with key greater than or equal to key */
+EAPI void * ecore_tree_closest_larger_get(Ecore_Tree *tree,
+ const void *key);
+/* Retrieve the value of node with key less than or equal to key */
+EAPI void * ecore_tree_closest_smaller_get(Ecore_Tree *tree,
+ const void *key);
+
+/* Set the value associated with key to value */
+EAPI int ecore_tree_set(Ecore_Tree *tree, void *key, void *value);
+/* Remove the key from the tree */
+EAPI int ecore_tree_remove(Ecore_Tree *tree, const void *key);
+
+/* Add a node to the tree */
+EAPI int ecore_tree_node_add(Ecore_Tree *tree,
+ Ecore_Tree_Node *node);
+/* Remove a node from the tree */
+EAPI int ecore_tree_node_remove(Ecore_Tree *tree,
+ Ecore_Tree_Node *node);
+
+/* For each node in the tree perform the for_each_func function */
+/* For this one pass in the node */
+EAPI int ecore_tree_for_each_node(Ecore_Tree *tree,
+ Ecore_For_Each for_each_func,
+ void *user_data);
+/* And here pass in the node's value */
+EAPI int ecore_tree_for_each_node_value(
+ Ecore_Tree *tree,
+ Ecore_For_Each
+ for_each_func,
+ void *user_data);
+
+/* Some basic node functions */
+/* Initialize a node */
+EAPI int ecore_tree_node_init(Ecore_Tree_Node *new_node);
+/* Allocate and initialize a new node */
+EAPI Ecore_Tree_Node *ecore_tree_node_new(void);
+/* Free the desired node */
+EAPI int ecore_tree_node_destroy(Ecore_Tree_Node *node,
+ Ecore_Free_Cb free_value,
+ Ecore_Free_Cb free_key);
+
+/* Set the node's key to key */
+EAPI int ecore_tree_node_key_set(Ecore_Tree_Node *node, void *key);
+/* Retrieve the key in node */
+EAPI void * ecore_tree_node_key_get(Ecore_Tree_Node *node);
+
+/* Set the node's value to value */
+EAPI int ecore_tree_node_value_set(Ecore_Tree_Node *node,
+ void *value);
+/* Retrieve the value in node */
+EAPI void * ecore_tree_node_value_get(Ecore_Tree_Node *node);
+
+/* Add a function to free the data stored in nodes */
+EAPI int ecore_tree_free_value_cb_set(Ecore_Tree *tree,
+ Ecore_Free_Cb free_value);
+/* Add a function to free the keys stored in nodes */
+EAPI int ecore_tree_free_key_cb_set(Ecore_Tree *tree,
+ Ecore_Free_Cb free_key);
+
+
+EAPI Ecore_Strbuf * ecore_strbuf_new(void);
+EAPI void ecore_strbuf_free(Ecore_Strbuf *buf);
+EAPI void ecore_strbuf_append(Ecore_Strbuf *buf, const char *str);
+EAPI void ecore_strbuf_append_char(Ecore_Strbuf *buf, char c);
+EAPI void ecore_strbuf_insert(Ecore_Strbuf *buf, const char *str,
+ size_t pos);
+# define ecore_strbuf_prepend(buf, str) ecore_strbuf_insert(buf, str, 0)
+EAPI const char * ecore_strbuf_string_get(Ecore_Strbuf *buf);
+EAPI size_t ecore_strbuf_length_get(Ecore_Strbuf *buf);
+EAPI int ecore_strbuf_replace(Ecore_Strbuf *buf, const char *str,
+ const char *with, unsigned int n);
+# define ecore_strbuf_replace_first(buf, str, with) \
+ ecore_strbuf_replace(buf, str, with, 1)
+EAPI int ecore_strbuf_replace_all(Ecore_Strbuf *buf,
+ const char *str,
+ const char *with);
+
+extern int ecore_str_compare(const void *key1, const void *key2);
+extern int ecore_direct_compare(const void *key1, const void *key2);
+extern unsigned int ecore_str_hash(const void *key);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ECORE_DATA_H */
diff --git a/src/tests/eina/Evas_Data.h b/src/tests/eina/Evas_Data.h
new file mode 100644
index 000000000..97848927b
--- /dev/null
+++ b/src/tests/eina/Evas_Data.h
@@ -0,0 +1,195 @@
+#ifndef _EVAS_DATA_H
+#define _EVAS_DATA_H
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_EVAS_BUILD
+# ifdef DLL_EXPORT
+# define EAPI __declspec(dllexport)
+# else
+# define EAPI
+# endif /* ! DLL_EXPORT */
+# else
+# define EAPI __declspec(dllimport)
+# endif /* ! EFL_EVAS_BUILD */
+#else
+# ifdef __GNUC__
+# if __GNUC__ >= 4
+# define EAPI __attribute__ ((visibility("default")))
+# else
+# define EAPI
+# endif
+# else
+# define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @file
+ * @brief These routines are used for Evas data types.
+ */
+
+typedef unsigned char Evas_Bool;
+
+typedef struct _Evas_Array_Hash Evas_Array_Hash;
+typedef struct _Evas_Hash Evas_Hash; /**< A Hash table handle */
+typedef struct _Evas_List Evas_List; /**< A generic linked list node handle */
+typedef struct _Evas_Object_List Evas_Object_List;
+
+struct _Evas_Hash
+{
+ int population;
+ Evas_Object_List *buckets[256];
+};
+
+struct _Evas_List /** A linked list node */
+{
+ void *data; /**< Pointer to list element payload */
+ Evas_List *next; /**< Next member in the list */
+ Evas_List *prev; /**< Previous member in the list */
+ struct _Evas_List_Accounting *accounting; /**< Private list accounting info - don't touch */
+};
+
+struct _Evas_Object_List
+{
+ Evas_Object_List *next, *prev;
+ Evas_Object_List *last;
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Evas Array Hash functions
+ */
+
+EAPI Evas_Array_Hash *evas_array_hash_new (void);
+EAPI void evas_array_hash_free (Evas_Array_Hash *hash);
+EAPI void evas_array_hash_add (Evas_Array_Hash *hash,
+ int key,
+ int data);
+EAPI int evas_array_hash_search (Evas_Array_Hash *hash,
+ int key);
+
+
+/*
+ * Evas Hash functions
+ */
+
+/* FIXME: add:
+ * api to add find, del members by data, size not just string and also
+ * provide hash generation functions settable by the app
+ *
+ * do we really need this? hmmm - let me think... there may be a better way
+ */
+EAPI Evas_Hash *evas_hash_add (Evas_Hash *hash,
+ const char *key,
+ const void *data);
+EAPI Evas_Hash *evas_hash_direct_add (Evas_Hash *hash,
+ const char *key,
+ const void *data);
+EAPI Evas_Hash *evas_hash_del (Evas_Hash *hash,
+ const char *key,
+ const void *data);
+EAPI void * evas_hash_find (const Evas_Hash *hash,
+ const char *key);
+EAPI void * evas_hash_modify (Evas_Hash *hash,
+ const char *key,
+ const void *data);
+EAPI int evas_hash_size (const Evas_Hash *hash);
+EAPI void evas_hash_free (Evas_Hash *hash);
+EAPI void evas_hash_foreach (const Evas_Hash *hash,
+ Evas_Bool (*func)(
+ const Evas_Hash *hash,
+ const char *
+ key,
+ void *data,
+ void *fdata),
+ const void *fdata);
+EAPI int evas_hash_alloc_error (void);
+
+
+/*
+ * Evas List functions
+ */
+
+EAPI Evas_List *evas_list_append (Evas_List *list,
+ const void *data);
+EAPI Evas_List *evas_list_prepend (Evas_List *list,
+ const void *data);
+EAPI Evas_List *evas_list_append_relative (Evas_List *list,
+ const void *data,
+ const void *relative);
+EAPI Evas_List *evas_list_append_relative_list (Evas_List *list,
+ const void *data,
+ Evas_List *relative);
+EAPI Evas_List *evas_list_prepend_relative (Evas_List *list,
+ const void *data,
+ const void *relative);
+EAPI Evas_List *evas_list_prepend_relative_list (Evas_List *list,
+ const void *data,
+ Evas_List *relative);
+EAPI Evas_List *evas_list_remove (Evas_List *list,
+ const void *data);
+EAPI Evas_List *evas_list_remove_list (Evas_List *list,
+ Evas_List *remove_list);
+EAPI Evas_List *evas_list_promote_list (Evas_List *list,
+ Evas_List *move_list);
+EAPI void * evas_list_find (const Evas_List *list,
+ const void *data);
+EAPI Evas_List *evas_list_find_list (const Evas_List *list,
+ const void *data);
+EAPI Evas_List *evas_list_free (Evas_List *list);
+EAPI Evas_List *evas_list_last (const Evas_List *list);
+EAPI Evas_List *evas_list_next (const Evas_List *list);
+EAPI Evas_List *evas_list_prev (const Evas_List *list);
+EAPI void * evas_list_data (const Evas_List *list);
+EAPI int evas_list_count (const Evas_List *list);
+EAPI void * evas_list_nth (const Evas_List *list, int n);
+EAPI Evas_List *evas_list_nth_list (const Evas_List *list, int n);
+EAPI Evas_List *evas_list_reverse (Evas_List *list);
+EAPI Evas_List *evas_list_sort (Evas_List *list,
+ int size,
+ int (*func)(void *,void *));
+EAPI int evas_list_alloc_error (void);
+
+
+/*
+ * Evas Object List functions
+ */
+
+EAPI void * evas_object_list_append (void *in_list,
+ void *in_item);
+EAPI void * evas_object_list_prepend (void *in_list,
+ void *in_item);
+EAPI void * evas_object_list_append_relative (void *in_list,
+ void *in_item,
+ void *in_relative);
+EAPI void * evas_object_list_prepend_relative (void *in_list,
+ void *in_item,
+ void *in_relative);
+EAPI void * evas_object_list_remove (void *in_list,
+ void *in_item);
+EAPI void * evas_object_list_find (void *in_list,
+ void *in_item);
+
+
+/*
+ * Evas Stringshare functions
+ */
+
+EAPI void evas_stringshare_init (void); /* not implemented */
+EAPI void evas_stringshare_shutdown (void); /* not implemented */
+EAPI const char *evas_stringshare_add (const char *str);
+EAPI void evas_stringshare_del (const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EVAS_DATA_H */
diff --git a/src/tests/eina/Makefile.am b/src/tests/eina/Makefile.am
new file mode 100644
index 000000000..f6810e22c
--- /dev/null
+++ b/src/tests/eina/Makefile.am
@@ -0,0 +1,142 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+benchdir = $(bindir)
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/include \
+-I$(top_builddir)/src/include \
+-I$(top_builddir)/src/lib \
+-DPACKAGE_BIN_DIR=\"$(bindir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \
+@CHECK_CFLAGS@ \
+@EINA_CFLAGS@ \
+@GLIB_CFLAGS@
+
+if EINA_HAVE_GLIB
+
+AM_CPPFLAGS += -DEINA_BENCH_HAVE_GLIB
+
+endif
+
+if EINA_ENABLE_BENCHMARK_E17
+
+AM_CPPFLAGS += -DEINA_ENABLE_BENCH_E17
+
+endif
+
+if EFL_ENABLE_TESTS
+
+check_PROGRAMS = eina_suite cxx_compile_test
+
+eina_suite_SOURCES = \
+eina_suite.c \
+eina_test_fp.c \
+eina_test_stringshare.c \
+eina_test_ustringshare.c\
+eina_test_ustr.c \
+eina_test_binshare.c \
+eina_test_binbuf.c \
+eina_test_inarray.c \
+eina_test_array.c \
+eina_test_clist.c \
+eina_test_error.c \
+eina_test_sched.c \
+eina_test_log.c \
+eina_test_magic.c \
+eina_test_inlist.c \
+eina_test_main.c \
+eina_test_counter.c \
+eina_test_lalloc.c \
+eina_test_hash.c \
+eina_test_iterator.c \
+eina_test_accessor.c \
+eina_test_module.c \
+eina_test_convert.c \
+eina_test_rbtree.c \
+eina_test_file.c \
+eina_test_benchmark.c \
+eina_test_mempool.c \
+eina_test_rectangle.c \
+eina_test_list.c \
+eina_test_matrixsparse.c \
+eina_test_tiler.c \
+eina_test_strbuf.c \
+eina_test_str.c \
+eina_test_quadtree.c \
+eina_test_simple_xml_parser.c \
+eina_test_value.c
+# eina_test_model.c
+
+eina_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libeina.la @EINA_LIBS@ -lm
+
+cxx_compile_test_SOURCES = cxx_compile_test.cxx
+cxx_compile_test_LDADD = $(top_builddir)/src/lib/libeina.la @EINA_LIBS@
+
+module_dummydir = $(libdir)/eina/test
+module_dummy_LTLIBRARIES = module_dummy.la
+
+module_dummy_la_SOURCES = \
+eina_test_module_dummy.c
+
+module_dummy_la_CPPFLAGS = \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/include \
+-I$(top_builddir)/src/include \
+-I$(top_builddir)/src/lib \
+@EFL_EINA_BUILD@
+module_dummy_la_LIBADD = $(top_builddir)/src/lib/libeina.la @EINA_LIBS@ -lm
+module_dummy_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+module_dummy_la_LIBTOOLFLAGS = --tag=disable-static
+
+endif
+
+if EFL_ENABLE_BENCHMARK
+
+bench_PROGRAMS = eina_bench
+
+eina_bench_SOURCES = \
+eina_bench.c \
+eina_bench_sort.c \
+eina_bench_hash.c \
+eina_bench_stringshare.c \
+eina_bench_convert.c \
+eina_bench_mempool.c \
+eina_bench_stringshare_e17.c \
+eina_bench_array.c \
+eina_bench_rectangle_pool.c \
+ecore_list.c \
+ecore_strings.c \
+ecore_hash.c \
+ecore_sheap.c \
+evas_hash.c \
+evas_list.c \
+evas_mempool.c \
+evas_object_list.c \
+evas_stringshare.c \
+eina_bench_quad.c \
+eina_bench.h \
+eina_suite.h \
+Ecore_Data.h \
+Evas_Data.h \
+evas_mempool.h
+
+if CITYHASH_BENCH
+noinst_LTLIBRARIES = libcity.la
+libcity_la_SOURCES = city.cc
+
+nodist_EXTRA_eina_bench_SOURCES = dummy.cc
+eina_bench_LDADD = @GLIB_LIBS@ $(top_builddir)/src/lib/libeina.la libcity.la @EINA_LIBS@
+else
+eina_bench_LDADD = @GLIB_LIBS@ $(top_builddir)/src/lib/libeina.la @EINA_LIBS@
+
+endif
+
+endif
+
+EXTRA_DIST = strlog
+
+clean-local:
+ rm -rf *.gcno ..\#..\#src\#*.gcov *.gcda
diff --git a/src/tests/eina/city.cc b/src/tests/eina/city.cc
new file mode 100644
index 000000000..36ff93b4e
--- /dev/null
+++ b/src/tests/eina/city.cc
@@ -0,0 +1,307 @@
+// Copyright (c) 2011 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// CityHash Version 1, by Geoff Pike and Jyrki Alakuijala
+//
+// This file provides CityHash64() and related functions.
+//
+// It's probably possible to create even faster hash functions by
+// writing a program that systematically explores some of the space of
+// possible hash functions, by using SIMD instructions, or by
+// compromising on hash quality.
+
+#include "city.h"
+
+#include <algorithm>
+
+using namespace std;
+
+#define UNALIGNED_LOAD64(p) (*(const uint64*)(p))
+#define UNALIGNED_LOAD32(p) (*(const uint32*)(p))
+
+#if !defined(LIKELY)
+#if defined(__GNUC__)
+#define LIKELY(x) (__builtin_expect(!!(x), 1))
+#else
+#define LIKELY(x) (x)
+#endif
+#endif
+
+// Some primes between 2^63 and 2^64 for various uses.
+static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
+static const uint64 k1 = 0xb492b66fbe98f273ULL;
+static const uint64 k2 = 0x9ae16a3b2f90404fULL;
+static const uint64 k3 = 0xc949d7c7509e6557ULL;
+
+// Bitwise right rotate. Normally this will compile to a single
+// instruction, especially if the shift is a manifest constant.
+static uint64 Rotate(uint64 val, int shift) {
+ // Avoid shifting by 64: doing so yields an undefined result.
+ return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
+}
+
+// Equivalent to Rotate(), but requires the second arg to be non-zero.
+// On x86-64, and probably others, it's possible for this to compile
+// to a single instruction if both args are already in registers.
+static uint64 RotateByAtLeast1(uint64 val, int shift) {
+ return (val >> shift) | (val << (64 - shift));
+}
+
+static uint64 ShiftMix(uint64 val) {
+ return val ^ (val >> 47);
+}
+
+static uint64 HashLen16(uint64 u, uint64 v) {
+ return Hash128to64(uint128(u, v));
+}
+
+static uint64 HashLen0to16(const char *s, size_t len) {
+ if (len > 8) {
+ uint64 a = UNALIGNED_LOAD64(s);
+ uint64 b = UNALIGNED_LOAD64(s + len - 8);
+ return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b;
+ }
+ if (len >= 4) {
+ uint64 a = UNALIGNED_LOAD32(s);
+ return HashLen16(len + (a << 3), UNALIGNED_LOAD32(s + len - 4));
+ }
+ if (len > 0) {
+ uint8 a = s[0];
+ uint8 b = s[len >> 1];
+ uint8 c = s[len - 1];
+ uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
+ uint32 z = len + (static_cast<uint32>(c) << 2);
+ return ShiftMix(y * k2 ^ z * k3) * k2;
+ }
+ return k2;
+}
+
+// This probably works well for 16-byte strings as well, but it may be overkill
+// in that case.
+static uint64 HashLen17to32(const char *s, size_t len) {
+ uint64 a = UNALIGNED_LOAD64(s) * k1;
+ uint64 b = UNALIGNED_LOAD64(s + 8);
+ uint64 c = UNALIGNED_LOAD64(s + len - 8) * k2;
+ uint64 d = UNALIGNED_LOAD64(s + len - 16) * k0;
+ return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d,
+ a + Rotate(b ^ k3, 20) - c + len);
+}
+
+// Return a 16-byte hash for 48 bytes. Quick and dirty.
+// Callers do best to use "random-looking" values for a and b.
+static pair<uint64, uint64> WeakHashLen32WithSeeds(
+ uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) {
+ a += w;
+ b = Rotate(b + a + z, 21);
+ uint64 c = a;
+ a += x;
+ a += y;
+ b += Rotate(a, 44);
+ return make_pair(a + z, b + c);
+}
+
+// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
+static pair<uint64, uint64> WeakHashLen32WithSeeds(
+ const char* s, uint64 a, uint64 b) {
+ return WeakHashLen32WithSeeds(UNALIGNED_LOAD64(s),
+ UNALIGNED_LOAD64(s + 8),
+ UNALIGNED_LOAD64(s + 16),
+ UNALIGNED_LOAD64(s + 24),
+ a,
+ b);
+}
+
+// Return an 8-byte hash for 33 to 64 bytes.
+static uint64 HashLen33to64(const char *s, size_t len) {
+ uint64 z = UNALIGNED_LOAD64(s + 24);
+ uint64 a = UNALIGNED_LOAD64(s) + (len + UNALIGNED_LOAD64(s + len - 16)) * k0;
+ uint64 b = Rotate(a + z, 52);
+ uint64 c = Rotate(a, 37);
+ a += UNALIGNED_LOAD64(s + 8);
+ c += Rotate(a, 7);
+ a += UNALIGNED_LOAD64(s + 16);
+ uint64 vf = a + z;
+ uint64 vs = b + Rotate(a, 31) + c;
+ a = UNALIGNED_LOAD64(s + 16) + UNALIGNED_LOAD64(s + len - 32);
+ z = UNALIGNED_LOAD64(s + len - 8);
+ b = Rotate(a + z, 52);
+ c = Rotate(a, 37);
+ a += UNALIGNED_LOAD64(s + len - 24);
+ c += Rotate(a, 7);
+ a += UNALIGNED_LOAD64(s + len - 16);
+ uint64 wf = a + z;
+ uint64 ws = b + Rotate(a, 31) + c;
+ uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0);
+ return ShiftMix(r * k0 + vs) * k2;
+}
+
+uint64 CityHash64(const char *s, size_t len) {
+ if (len <= 32) {
+ if (len <= 16) {
+ return HashLen0to16(s, len);
+ } else {
+ return HashLen17to32(s, len);
+ }
+ } else if (len <= 64) {
+ return HashLen33to64(s, len);
+ }
+
+ // For strings over 64 bytes we hash the end first, and then as we
+ // loop we keep 56 bytes of state: v, w, x, y, and z.
+ uint64 x = UNALIGNED_LOAD64(s);
+ uint64 y = UNALIGNED_LOAD64(s + len - 16) ^ k1;
+ uint64 z = UNALIGNED_LOAD64(s + len - 56) ^ k0;
+ pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, y);
+ pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, len * k1, k0);
+ z += ShiftMix(v.second) * k1;
+ x = Rotate(z + x, 39) * k1;
+ y = Rotate(y, 33) * k1;
+
+ // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
+ len = (len - 1) & ~static_cast<size_t>(63);
+ do {
+ x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1;
+ y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
+ x ^= w.second;
+ y ^= v.first;
+ z = Rotate(z ^ w.first, 33);
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
+ std::swap(z, x);
+ s += 64;
+ len -= 64;
+ } while (len != 0);
+ return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
+ HashLen16(v.second, w.second) + x);
+}
+
+uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) {
+ return CityHash64WithSeeds(s, len, k2, seed);
+}
+
+uint64 CityHash64WithSeeds(const char *s, size_t len,
+ uint64 seed0, uint64 seed1) {
+ return HashLen16(CityHash64(s, len) - seed0, seed1);
+}
+
+// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
+// of any length representable in ssize_t. Based on City and Murmur.
+static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
+ uint64 a = Uint128Low64(seed);
+ uint64 b = Uint128High64(seed);
+ uint64 c = 0;
+ uint64 d = 0;
+ ssize_t l = len - 16;
+ if (l <= 0) { // len <= 16
+ c = b * k1 + HashLen0to16(s, len);
+ d = Rotate(a + (len >= 8 ? UNALIGNED_LOAD64(s) : c), 32);
+ } else { // len > 16
+ c = HashLen16(UNALIGNED_LOAD64(s + len - 8) + k1, a);
+ d = HashLen16(b + len, c + UNALIGNED_LOAD64(s + len - 16));
+ a += d;
+ do {
+ a ^= ShiftMix(UNALIGNED_LOAD64(s) * k1) * k1;
+ a *= k1;
+ b ^= a;
+ c ^= ShiftMix(UNALIGNED_LOAD64(s + 8) * k1) * k1;
+ c *= k1;
+ d ^= c;
+ s += 16;
+ l -= 16;
+ } while (l > 0);
+ }
+ a = HashLen16(a, c);
+ b = HashLen16(d, b);
+ return uint128(a ^ b, HashLen16(b, a));
+}
+
+uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
+ if (len < 128) {
+ return CityMurmur(s, len, seed);
+ }
+
+ // We expect len >= 128 to be the common case. Keep 56 bytes of state:
+ // v, w, x, y, and z.
+ pair<uint64, uint64> v, w;
+ uint64 x = Uint128Low64(seed);
+ uint64 y = Uint128High64(seed);
+ uint64 z = len * k1;
+ v.first = Rotate(y ^ k1, 49) * k1 + UNALIGNED_LOAD64(s);
+ v.second = Rotate(v.first, 42) * k1 + UNALIGNED_LOAD64(s + 8);
+ w.first = Rotate(y + z, 35) * k1 + x;
+ w.second = Rotate(x + UNALIGNED_LOAD64(s + 88), 53) * k1;
+
+ // This is the same inner loop as CityHash64(), manually unrolled.
+ do {
+ x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1;
+ y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
+ x ^= w.second;
+ y ^= v.first;
+ z = Rotate(z ^ w.first, 33);
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
+ std::swap(z, x);
+ s += 64;
+ x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1;
+ y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
+ x ^= w.second;
+ y ^= v.first;
+ z = Rotate(z ^ w.first, 33);
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
+ std::swap(z, x);
+ s += 64;
+ len -= 128;
+ } while (LIKELY(len >= 128));
+ y += Rotate(w.first, 37) * k0 + z;
+ x += Rotate(v.first + z, 49) * k0;
+ // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
+ for (size_t tail_done = 0; tail_done < len; ) {
+ tail_done += 32;
+ y = Rotate(y - x, 42) * k0 + v.second;
+ w.first += UNALIGNED_LOAD64(s + len - tail_done + 16);
+ x = Rotate(x, 49) * k0 + w.first;
+ w.first += v.first;
+ v = WeakHashLen32WithSeeds(s + len - tail_done, v.first, v.second);
+ }
+ // At this point our 48 bytes of state should contain more than
+ // enough information for a strong 128-bit hash. We use two
+ // different 48-byte-to-8-byte hashes to get a 16-byte final result.
+ x = HashLen16(x, v.first);
+ y = HashLen16(y, w.first);
+ return uint128(HashLen16(x + v.second, w.second) + y,
+ HashLen16(x + w.second, y + v.second));
+}
+
+uint128 CityHash128(const char *s, size_t len) {
+ if (len >= 16) {
+ return CityHash128WithSeed(s + 16,
+ len - 16,
+ uint128(UNALIGNED_LOAD64(s) ^ k3,
+ UNALIGNED_LOAD64(s + 8)));
+ } else if (len >= 8) {
+ return CityHash128WithSeed(NULL,
+ 0,
+ uint128(UNALIGNED_LOAD64(s) ^ (len * k0),
+ UNALIGNED_LOAD64(s + len - 8) ^ k1));
+ } else {
+ return CityHash128WithSeed(s, len, uint128(k0, k1));
+ }
+}
diff --git a/src/tests/eina/city.h b/src/tests/eina/city.h
new file mode 100644
index 000000000..a9c297fee
--- /dev/null
+++ b/src/tests/eina/city.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2011 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// CityHash Version 1, by Geoff Pike and Jyrki Alakuijala
+//
+// This file provides a few functions for hashing strings. On x86-64
+// hardware in 2011, CityHash64() is faster than other high-quality
+// hash functions, such as Murmur. This is largely due to higher
+// instruction-level parallelism. CityHash64() and CityHash128() also perform
+// well on hash-quality tests.
+//
+// CityHash128() is optimized for relatively long strings and returns
+// a 128-bit hash. For strings more than about 2000 bytes it can be
+// faster than CityHash64().
+//
+// Functions in the CityHash family are not suitable for cryptography.
+//
+// WARNING: This code has not been tested on big-endian platforms!
+// It is known to work well on little-endian platforms that have a small penalty
+// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
+//
+// By the way, for some hash functions, given strings a and b, the hash
+// of a+b is easily derived from the hashes of a and b. This property
+// doesn't hold for any hash functions in this file.
+
+#ifndef CITY_HASH_H_
+#define CITY_HASH_H_
+
+#include <stdlib.h> // for size_t.
+#include <stdint.h>
+#include <utility>
+
+typedef uint8_t uint8;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+typedef std::pair<uint64, uint64> uint128;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+inline uint64 Uint128Low64(const uint128& x) { return x.first; }
+inline uint64 Uint128High64(const uint128& x) { return x.second; }
+
+// Hash function for a byte array.
+uint64 CityHash64(const char *buf, size_t len);
+// Hash function for a byte array. For convenience, a 64-bit seed is also
+// hashed into the result.
+uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed);
+
+// Hash function for a byte array. For convenience, two seeds are also
+// hashed into the result.
+uint64 CityHash64WithSeeds(const char *buf, size_t len,
+ uint64 seed0, uint64 seed1);
+
+// Hash function for a byte array.
+uint128 CityHash128(const char *s, size_t len);
+
+// Hash function for a byte array. For convenience, a 128-bit seed is also
+// hashed into the result.
+uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed);
+
+// Hash 128 input bits down to 64 bits of output.
+// This is intended to be a reasonably good hash function.
+inline uint64 Hash128to64(const uint128& x) {
+ // Murmur-inspired hashing.
+ const uint64 kMul = 0x9ddfea08eb382d69ULL;
+ uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
+ a ^= (a >> 47);
+ uint64 b = (Uint128High64(x) ^ a) * kMul;
+ b ^= (b >> 47);
+ b *= kMul;
+ return b;
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif // CITY_HASH_H_
diff --git a/src/tests/eina/cxx_compile_test.cxx b/src/tests/eina/cxx_compile_test.cxx
new file mode 100644
index 000000000..7d8af769b
--- /dev/null
+++ b/src/tests/eina/cxx_compile_test.cxx
@@ -0,0 +1,34 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2012 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "Eina.h"
+
+#include <iostream>
+using namespace std;
+
+int main()
+{
+ eina_init();
+ cout << "Eina compiles with C++!";
+ eina_shutdown();
+ return 0;
+}
diff --git a/src/tests/eina/ecore_hash.c b/src/tests/eina/ecore_hash.c
new file mode 100644
index 000000000..f957d529c
--- /dev/null
+++ b/src/tests/eina/ecore_hash.c
@@ -0,0 +1,949 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Ecore_Data.h"
+
+#define PRIME_TABLE_MAX 21
+#define PRIME_MIN 17
+#define PRIME_MAX 16777213
+
+#define ECORE_HASH_CHAIN_MAX 3
+
+#define ECORE_COMPUTE_HASH(hash, key) hash->hash_func(key) % \
+ ecore_prime_table[hash->size];
+
+#define ECORE_HASH_INCREASE(hash) ((hash && ecore_prime_table[hash->size] < \
+ PRIME_MAX) ? \
+ (hash->nodes / \
+ ecore_prime_table[hash->size]) > \
+ ECORE_HASH_CHAIN_MAX : FALSE)
+#define ECORE_HASH_REDUCE(hash) ((hash && ecore_prime_table[hash->size] > \
+ PRIME_MIN) ? \
+ (double)hash->nodes / \
+ (double)ecore_prime_table[hash->size - 1] \
+ < ((double)ECORE_HASH_CHAIN_MAX * \
+ 0.375) : FALSE)
+
+
+static const unsigned int ecore_prime_table[] =
+{
+ 17, 31, 61, 127, 257, 509, 1021,
+ 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573,
+ 2097143, 4194301, 8388617, 16777213
+};
+
+
+/* Private hash manipulation functions */
+static int _ecore_hash_node_add(Ecore_Hash *hash,
+ Ecore_Hash_Node *node);
+static Ecore_Hash_Node * _ecore_hash_node_get(Ecore_Hash *hash,
+ const void *key);
+static int _ecore_hash_increase(Ecore_Hash *hash);
+static int _ecore_hash_decrease(Ecore_Hash *hash);
+static inline int _ecore_hash_rehash(Ecore_Hash *hash,
+ Ecore_Hash_Node **old_table,
+ int old_size);
+static int _ecore_hash_bucket_destroy(Ecore_Hash_Node *list,
+ Ecore_Free_Cb keyd,
+ Ecore_Free_Cb valued);
+static inline Ecore_Hash_Node *_ecore_hash_bucket_get(Ecore_Hash *hash,
+ Ecore_Hash_Node *bucket,
+ const void *key);
+
+static Ecore_Hash_Node * _ecore_hash_node_new(void *key, void *value);
+static int _ecore_hash_node_init(Ecore_Hash_Node *node,
+ void *key,
+ void *value);
+static int _ecore_hash_node_destroy(Ecore_Hash_Node *node,
+ Ecore_Free_Cb keyd,
+ Ecore_Free_Cb valued);
+
+/**
+ * @defgroup Ecore_Data_Hash_ADT_Creation_Group Hash Creation Functions
+ *
+ * Functions that create hash tables.
+ */
+
+/**
+ * Creates and initializes a new hash
+ * @param hash_func The function for determining hash position.
+ * @param compare The function for comparing node keys.
+ * @return @c NULL on error, a new hash on success.
+ * @ingroup Ecore_Data_Hash_ADT_Creation_Group
+ */
+EAPI Ecore_Hash *
+ecore_hash_new(Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare)
+{
+ Ecore_Hash *new_hash = (Ecore_Hash *)malloc(sizeof(Ecore_Hash));
+ if (!new_hash)
+ return NULL;
+
+ if (!ecore_hash_init(new_hash, hash_func, compare))
+ {
+ FREE(new_hash);
+ return NULL;
+ }
+
+ return new_hash;
+}
+
+/**
+ * Initializes the given hash.
+ * @param hash The given hash.
+ * @param hash_func The function used for hashing node keys.
+ * @param compare The function used for comparing node keys.
+ * @return @c TRUE on success, @c FALSE on an error.
+ * @ingroup Ecore_Data_Hash_ADT_Creation_Group
+ */
+EAPI int
+ecore_hash_init(Ecore_Hash *hash,
+ Ecore_Hash_Cb hash_func,
+ Ecore_Compare_Cb compare)
+{
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+
+ memset(hash, 0, sizeof(Ecore_Hash));
+
+ hash->hash_func = hash_func;
+ hash->compare = compare;
+
+ hash->buckets = (Ecore_Hash_Node **)calloc(ecore_prime_table[0],
+ sizeof(Ecore_Hash_Node *));
+
+ return TRUE;
+}
+
+/**
+ * @defgroup Ecore_Data_Hash_ADT_Destruction_Group Hash Destruction Functions
+ *
+ * Functions that destroy hash tables and their contents.
+ */
+
+/**
+ * Sets the function to destroy the keys of the given hash.
+ * @param hash The given hash.
+ * @param function The function used to free the node keys. NULL is a
+ * valid value and means that no function will be called.
+ * @return @c TRUE on success, @c FALSE on error.
+ * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
+ */
+EAPI int
+ecore_hash_free_key_cb_set(Ecore_Hash *hash, Ecore_Free_Cb function)
+{
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+
+ hash->free_key = function;
+
+ return TRUE;
+}
+
+/**
+ * Sets the function to destroy the values in the given hash.
+ * @param hash The given hash.
+ * @param function The function that will free the node values. NULL is a
+ * valid value and means that no function will be called.
+ * @return @c TRUE on success, @c FALSE on error
+ * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
+ */
+EAPI int
+ecore_hash_free_value_cb_set(Ecore_Hash *hash, Ecore_Free_Cb function)
+{
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+
+ hash->free_value = function;
+
+ return TRUE;
+}
+
+/**
+ * @defgroup Ecore_Data_Hash_ADT_Data_Group Hash Data Functions
+ *
+ * Functions that set, access and delete values from the hash tables.
+ */
+
+/**
+ * Sets a key-value pair in the given hash table.
+ * @param hash The given hash table.
+ * @param key The key.
+ * @param value The value.
+ * @return @c TRUE if successful, @c FALSE if not.
+ * @ingroup Ecore_Data_Hash_ADT_Data_Group
+ */
+EAPI int
+ecore_hash_set(Ecore_Hash *hash, void *key, void *value)
+{
+ int ret = FALSE;
+ Ecore_Hash_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+
+ node = _ecore_hash_node_get(hash, key);
+ if (node)
+ {
+ if (hash->free_key)
+ hash->free_key(key);
+
+ if (node->value && hash->free_value)
+ hash->free_value(node->value);
+
+ node->value = value;
+ ret = TRUE;
+ }
+ else
+ {
+ node = _ecore_hash_node_new(key, value);
+ if (node)
+ ret = _ecore_hash_node_add(hash, node);
+ }
+
+ return ret;
+}
+
+/**
+ * Sets all key-value pairs from set in the given hash table.
+ * @param hash The given hash table.
+ * @param set The hash table to import.
+ * @return @c TRUE if successful, @c FALSE if not.
+ * @ingroup Ecore_Data_Hash_ADT_Data_Group
+ */
+EAPI int
+ecore_hash_hash_set(Ecore_Hash *hash, Ecore_Hash *set)
+{
+ unsigned int i;
+ Ecore_Hash_Node *node, *old;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+ CHECK_PARAM_POINTER_RETURN("set", set, FALSE);
+
+ for (i = 0; i < ecore_prime_table[set->size]; i++)
+ {
+ /* Hash into a new list to avoid loops of rehashing the same nodes */
+ while ((old = set->buckets[i]))
+ {
+ set->buckets[i] = old->next;
+ old->next = NULL;
+ node = _ecore_hash_node_get(hash, old->key);
+ if (node)
+ {
+ /* This key already exists. Delete the old and add the new
+ * value */
+ if (hash->free_key)
+ hash->free_key(node->key);
+
+ if (hash->free_value)
+ hash->free_key(node->value);
+
+ node->key = old->key;
+ node->value = old->value;
+ free(old);
+ }
+ else
+ _ecore_hash_node_add(hash, old);
+ }
+ }
+ FREE(set->buckets);
+ ecore_hash_init(set, set->hash_func, set->compare);
+ return TRUE;
+}
+
+/**
+ * Frees the hash table and the data contained inside it.
+ * @param hash The hash table to destroy.
+ * @return @c TRUE on success, @c FALSE on error.
+ * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
+ */
+EAPI void
+ecore_hash_destroy(Ecore_Hash *hash)
+{
+ unsigned int i = 0;
+
+ CHECK_PARAM_POINTER("hash", hash);
+
+ if (hash->buckets)
+ {
+ while (i < ecore_prime_table[hash->size])
+ {
+ if (hash->buckets[i])
+ {
+ Ecore_Hash_Node *bucket;
+
+ /*
+ * Remove the bucket list to avoid possible recursion
+ * on the free callbacks.
+ */
+ bucket = hash->buckets[i];
+ hash->buckets[i] = NULL;
+ _ecore_hash_bucket_destroy(bucket,
+ hash->free_key,
+ hash->free_value);
+ }
+
+ i++;
+ }
+
+ FREE(hash->buckets);
+ }
+
+ FREE(hash);
+
+ return;
+}
+
+/**
+ * @defgroup Ecore_Data_Hash_ADT_Traverse_Group Hash Traverse Functions
+ *
+ * Functions that iterate through hash tables.
+ */
+
+/**
+ * Counts the number of nodes in a hash table.
+ * @param hash The hash table to count current nodes.
+ * @return The number of nodes in the hash.
+ * @ingroup Ecore_Data_Hash_ADT_Destruction_Group
+ */
+EAPI int
+ecore_hash_count(Ecore_Hash *hash)
+{
+ CHECK_PARAM_POINTER_RETURN("hash", hash, 0);
+
+ return hash->nodes;
+}
+
+/**
+ * Runs the @p for_each_func function on each entry in the given hash.
+ * @param hash The given hash.
+ * @param for_each_func The function that each entry is passed to.
+ * @param user_data a pointer passed to calls of for_each_func
+ * @return TRUE on success, FALSE otherwise.
+ * @ingroup Ecore_Data_Hash_ADT_Traverse_Group
+ */
+EAPI int
+ecore_hash_for_each_node(Ecore_Hash *hash,
+ Ecore_For_Each for_each_func,
+ void *user_data)
+{
+ unsigned int i = 0;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+ CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE);
+
+ while (i < ecore_prime_table[hash->size])
+ {
+ if (hash->buckets[i])
+ {
+ Ecore_Hash_Node *node;
+
+ for (node = hash->buckets[i]; node; node = node->next)
+ {
+ for_each_func(node, user_data);
+ }
+ }
+
+ i++;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Retrieves an ecore_list of all keys in the given hash.
+ * @param hash The given hash.
+ * @return new ecore_list on success, NULL otherwise
+ * @ingroup Ecore_Data_Hash_ADT_Traverse_Group
+ */
+EAPI Ecore_List *
+ecore_hash_keys(Ecore_Hash *hash)
+{
+ unsigned int i = 0;
+ Ecore_List *keys;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
+
+ keys = ecore_list_new();
+ while (i < ecore_prime_table[hash->size])
+ {
+ if (hash->buckets[i])
+ {
+ Ecore_Hash_Node *node;
+
+ for (node = hash->buckets[i]; node; node = node->next)
+ {
+ ecore_list_append(keys, node->key);
+ }
+ }
+
+ i++;
+ }
+ ecore_list_first_goto(keys);
+
+ return keys;
+}
+
+/**
+ * Prints the distribution of the given hash table for graphing.
+ * @param hash The given hash table.
+ */
+EAPI void
+ecore_hash_dump_graph(Ecore_Hash *hash)
+{
+ unsigned int i;
+
+ for (i = 0; i < ecore_prime_table[hash->size]; i++)
+ if (hash->buckets[i])
+ {
+ int n = 0;
+ Ecore_Hash_Node *node;
+ for (node = hash->buckets[i]; node; node = node->next)
+ n++;
+ printf("%d\t%u", i, n);
+ }
+ else
+ printf("%d\t0", i);
+
+}
+
+/**
+ * Prints the distribution of the given hash table for graphing.
+ * @param hash The given hash table.
+ */
+EAPI void
+ecore_hash_dump_stats(Ecore_Hash *hash)
+{
+ unsigned int i;
+ double variance, sum_n_2 = 0, sum_n = 0;
+
+ for (i = 0; i < ecore_prime_table[hash->size]; i++)
+ {
+ if (hash->buckets[i])
+ {
+ int n = 0;
+ Ecore_Hash_Node *node;
+ for (node = hash->buckets[i]; node; node = node->next)
+ n++;
+ sum_n_2 += ((double)n * (double)n);
+ sum_n += (double)n;
+ }
+ }
+ variance = (sum_n_2 - ((sum_n * sum_n) / (double)i)) / (double)i;
+ printf("Average length: %f\n\tvariance^2: %f", (sum_n / (double)i),
+ variance);
+}
+
+static int
+_ecore_hash_bucket_destroy(Ecore_Hash_Node *list,
+ Ecore_Free_Cb keyd,
+ Ecore_Free_Cb valued)
+{
+ Ecore_Hash_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ for (node = list; node; node = list)
+ {
+ list = list->next;
+ _ecore_hash_node_destroy(node, keyd, valued);
+ }
+
+ return TRUE;
+}
+
+/*
+ * @brief Add the node to the hash table
+ * @param hash: the hash table to add the key
+ * @param node: the node to add to the hash table
+ * @return Returns FALSE on error, TRUE on success
+ */
+static int
+_ecore_hash_node_add(Ecore_Hash *hash, Ecore_Hash_Node *node)
+{
+ unsigned long hash_val;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+ CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
+
+ /* Check to see if the hash needs to be resized */
+ if (ECORE_HASH_INCREASE(hash))
+ _ecore_hash_increase(hash);
+
+ /* Compute the position in the table */
+ if (!hash->hash_func)
+ hash_val = (unsigned long)node->key % ecore_prime_table[hash->size];
+ else
+ hash_val = ECORE_COMPUTE_HASH(hash, node->key);
+
+ /* Prepend the node to the list at the index position */
+ node->next = hash->buckets[hash_val];
+ hash->buckets[hash_val] = node;
+ hash->nodes++;
+
+ return TRUE;
+}
+
+/**
+ * Retrieves the value associated with the given key from the given hash
+ * table.
+ * @param hash The given hash table.
+ * @param key The key to search for.
+ * @return The value corresponding to key on success, @c NULL otherwise.
+ * @ingroup Ecore_Data_Hash_ADT_Data_Group
+ */
+EAPI void *
+ecore_hash_get(Ecore_Hash *hash, const void *key)
+{
+ void *data;
+ Ecore_Hash_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
+
+ node = _ecore_hash_node_get(hash, key);
+ if (!node)
+ return NULL;
+
+ data = node->value;
+
+ return data;
+}
+
+/**
+ * Removes the value associated with the given key in the given hash
+ * table.
+ * @param hash The given hash table.
+ * @param key The key to search for.
+ * @return The value corresponding to the key on success. @c NULL is
+ * returned if there is an error.
+ * @ingroup Ecore_Data_Hash_ADT_Data_Group
+ */
+EAPI void *
+ecore_hash_remove(Ecore_Hash *hash, const void *key)
+{
+ Ecore_Hash_Node *node = NULL;
+ Ecore_Hash_Node *list;
+ unsigned long hash_val;
+ void *ret = NULL;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
+
+ /* Compute the position in the table */
+ if (!hash->hash_func)
+ hash_val = (unsigned long )key % ecore_prime_table[hash->size];
+ else
+ hash_val = ECORE_COMPUTE_HASH(hash, key);
+
+ /*
+ * If their is a list that could possibly hold the key/value pair
+ * traverse it and remove the hash node.
+ */
+ if (hash->buckets[hash_val])
+ {
+ list = hash->buckets[hash_val];
+
+ /*
+ * Traverse the list to find the specified key
+ */
+ node = list;
+ if (hash->compare)
+ while ((node) && (hash->compare(node->key, key) != 0))
+ {
+ list = node;
+ node = node->next;
+ }
+ else
+ while ((node) && (node->key != key))
+ {
+ list = node;
+ node = node->next;
+ }
+
+ /*
+ * Remove the node with the matching key and free it's memory
+ */
+ if (node)
+ {
+ if (list == node)
+ hash->buckets[hash_val] = node->next;
+ else
+ list->next = node->next;
+
+ ret = node->value;
+ node->value = NULL;
+ _ecore_hash_node_destroy(node, hash->free_key, NULL);
+ hash->nodes--;
+ }
+ }
+
+ if (ECORE_HASH_REDUCE(hash))
+ _ecore_hash_decrease(hash);
+
+ return ret;
+}
+
+/**
+ * Retrieves the first value that matches
+ * table.
+ * @param hash The given hash table.
+ * @param key The key to search for.
+ * @return The value corresponding to key on success, @c NULL otherwise.
+ * @ingroup Ecore_Data_Hash_ADT_Data_Group
+ */
+EAPI void *
+ecore_hash_find(Ecore_Hash *hash, Ecore_Compare_Cb compare, const void *value)
+{
+ unsigned int i = 0;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
+ CHECK_PARAM_POINTER_RETURN("compare", compare, NULL);
+ CHECK_PARAM_POINTER_RETURN("value", value, NULL);
+
+ while (i < ecore_prime_table[hash->size])
+ {
+ if (hash->buckets[i])
+ {
+ Ecore_Hash_Node *node;
+
+ for (node = hash->buckets[i]; node; node = node->next)
+ {
+ if (!compare(node->value, value))
+ return node->value;
+ }
+ }
+
+ i++;
+ }
+
+ return NULL;
+}
+
+/*
+ * @brief Retrieve the node associated with key
+ * @param hash: the hash table to search for the key
+ * @param key: the key to search for in the hash table
+ * @return Returns NULL on error, node corresponding to key on success
+ */
+static Ecore_Hash_Node *
+_ecore_hash_node_get(Ecore_Hash *hash, const void *key)
+{
+ unsigned long hash_val;
+ Ecore_Hash_Node *node = NULL;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, NULL);
+
+ if (!hash->buckets)
+ return NULL;
+
+ /* Compute the position in the table */
+ if (!hash->hash_func)
+ hash_val = (unsigned long)key % ecore_prime_table[hash->size];
+ else
+ hash_val = ECORE_COMPUTE_HASH(hash, key);
+
+ /* Grab the bucket at the specified position */
+ if (hash->buckets[hash_val])
+ {
+ node = _ecore_hash_bucket_get(hash, hash->buckets[hash_val], key);
+ /*
+ * Move matched node to the front of the list as it's likely
+ * to be searched for again soon.
+ */
+ if (node && node != hash->buckets[hash_val])
+ {
+ node->next = hash->buckets[hash_val];
+ hash->buckets[hash_val] = node;
+ }
+ }
+
+ return node;
+}
+
+/*
+ * @brief Search the hash bucket for a specified key
+ * @param hash: the hash table to retrieve the comparison function
+ * @param bucket: the list to search for the key
+ * @param key: the key to search for in the list
+ * @return Returns NULL on error or not found, the found node on success
+ */
+static inline Ecore_Hash_Node *
+_ecore_hash_bucket_get(Ecore_Hash *hash,
+ Ecore_Hash_Node *bucket,
+ const void *key)
+{
+ Ecore_Hash_Node *prev = NULL;
+ Ecore_Hash_Node *node = NULL;
+
+ /*
+ * Traverse the list to find the desired node, if the node is in the
+ * list, then return the node.
+ */
+ if (hash->compare)
+ for (node = bucket; node; node = node->next)
+ {
+ if (hash->compare(node->key, key) == 0)
+ break;
+
+ prev = node;
+ }
+ else
+ for (node = bucket; node; node = node->next)
+ {
+ if (node->key == key)
+ break;
+
+ prev = node;
+ }
+
+ /*
+ * Remove node from the list to replace it at the beginning.
+ */
+ if (node && prev)
+ {
+ prev->next = node->next;
+ node->next = NULL;
+ }
+
+ return node;
+}
+
+/*
+ * @brief Increase the size of the hash table by approx. 2 * current size
+ * @param hash: the hash table to increase the size of
+ * @return Returns TRUE on success, FALSE on error
+ */
+static int
+_ecore_hash_increase(Ecore_Hash *hash)
+{
+ void *old;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+
+ /* Max size reached so return FALSE */
+ if ((ecore_prime_table[hash->size] == PRIME_MAX) ||
+ (hash->size == PRIME_TABLE_MAX))
+ return FALSE;
+
+ /*
+ * Increase the size of the hash and save a pointer to the old data
+ */
+ hash->size++;
+ old = hash->buckets;
+
+ /*
+ * Allocate a new bucket area, of the new larger size
+ */
+ hash->buckets =
+ calloc(ecore_prime_table[hash->size], sizeof(Ecore_Hash_Node *));
+
+ /*
+ * Make sure the allocation succeeded, if not replace the old data and
+ * return a failure.
+ */
+ if (!hash->buckets)
+ {
+ hash->buckets = old;
+ hash->size--;
+ return FALSE;
+ }
+
+ hash->nodes = 0;
+
+ /*
+ * Now move all of the old data into the new bucket area
+ */
+ if (_ecore_hash_rehash(hash, old, hash->size - 1))
+ {
+ FREE(old);
+ return TRUE;
+ }
+
+ /*
+ * Free the old buckets regardless of success.
+ */
+ FREE(old);
+
+ return FALSE;
+}
+
+/*
+ * @brief Decrease the size of the hash table by < 1/2 * current size
+ * @param hash: the hash table to decrease the size of
+ * @return Returns TRUE on success, FALSE on error
+ */
+static int
+_ecore_hash_decrease(Ecore_Hash *hash)
+{
+ Ecore_Hash_Node **old;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+
+ if (ecore_prime_table[hash->size] == PRIME_MIN)
+ return FALSE;
+
+ /*
+ * Decrease the hash size and store a pointer to the old data
+ */
+ hash->size--;
+ old = hash->buckets;
+
+ /*
+ * Allocate a new area to store the data
+ */
+ hash->buckets = (Ecore_Hash_Node **)calloc(ecore_prime_table[hash->size],
+ sizeof(Ecore_Hash_Node *));
+
+ /*
+ * Make sure allocation succeeded otherwise rreturn to the previous
+ * state
+ */
+ if (!hash->buckets)
+ {
+ hash->buckets = old;
+ hash->size++;
+ return FALSE;
+ }
+
+ hash->nodes = 0;
+
+ if (_ecore_hash_rehash(hash, old, hash->size + 1))
+ {
+ FREE(old);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * @brief Rehash the nodes of a table into the hash table
+ * @param hash: the hash to place the nodes of the table
+ * @param table: the table to remove the nodes from and place in hash
+ * @return Returns TRUE on success, FALSE on error
+ */
+static inline int
+_ecore_hash_rehash(Ecore_Hash *hash, Ecore_Hash_Node **old_table, int old_size)
+{
+ unsigned int i;
+ Ecore_Hash_Node *old;
+
+ CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE);
+ CHECK_PARAM_POINTER_RETURN("old_table", old_table, FALSE);
+
+ for (i = 0; i < ecore_prime_table[old_size]; i++)
+ {
+ /* Hash into a new list to avoid loops of rehashing the same nodes */
+ while ((old = old_table[i]))
+ {
+ old_table[i] = old->next;
+ old->next = NULL;
+ _ecore_hash_node_add(hash, old);
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * @brief Create a new hash node for key and value storage
+ * @param key: the key for this node
+ * @param value: the value that the key references
+ * @return Returns NULL on error, a new hash node on success
+ */
+static Ecore_Hash_Node *
+_ecore_hash_node_new(void *key, void *value)
+{
+ Ecore_Hash_Node *node;
+
+ node = (Ecore_Hash_Node *)malloc(sizeof(Ecore_Hash_Node));
+ if (!node)
+ return NULL;
+
+ if (!_ecore_hash_node_init(node, key, value))
+ {
+ FREE(node);
+ return NULL;
+ }
+
+ return node;
+}
+
+/*
+ * @brief Initialize a hash node to some sane default values
+ * @param node: the node to set the values
+ * @param key: the key to reference this node
+ * @param value: the value that key refers to
+ * @return Returns TRUE on success, FALSE on error
+ */
+static int
+_ecore_hash_node_init(Ecore_Hash_Node *node, void *key, void *value)
+{
+ CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
+
+ node->key = key;
+ node->value = value;
+
+ return TRUE;
+}
+
+/*
+ * @brief Destroy a node and call the specified callbacks to free data
+ * @param node: the node to be destroyed
+ * @param keyd: the function to free the key
+ * @param valued: the function to free the value
+ * @return Returns TRUE on success, FALSE on error
+ */
+static int
+_ecore_hash_node_destroy(Ecore_Hash_Node *node,
+ Ecore_Free_Cb keyd,
+ Ecore_Free_Cb valued)
+{
+ CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
+
+ if (keyd)
+ keyd(node->key);
+
+ if (valued)
+ valued(node->value);
+
+ FREE(node);
+
+ return TRUE;
+}
+
+int
+ecore_str_compare(const void *key1, const void *key2)
+{
+ const char *k1, *k2;
+
+ if (!key1 || !key2)
+ return ecore_direct_compare(key1, key2);
+ else if (key1 == key2)
+ return 0;
+
+ k1 = key1;
+ k2 = key2;
+
+ return strcmp(k1, k2);
+}
+
+unsigned int
+ecore_str_hash(const void *key)
+{
+ int i;
+ unsigned int mask;
+ unsigned int value = 0;
+ const char *k = key;
+
+ if (!k)
+ return 0;
+
+ mask = (sizeof(unsigned int) * 8) - 1;
+
+ for (i = 0; k[i] != '\0'; i++)
+ {
+ value ^= ((unsigned int)k[i] << ((i * 5) & mask));
+ }
+
+ return value;
+}
diff --git a/src/tests/eina/ecore_list.c b/src/tests/eina/ecore_list.c
new file mode 100644
index 000000000..7da44178b
--- /dev/null
+++ b/src/tests/eina/ecore_list.c
@@ -0,0 +1,2162 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "Ecore_Data.h"
+
+/* Some tests showed that beyond that value heap sort is faster than merge sort
+ * (in this implementation). This value has to be changed or at least review
+ * if someone is changing the implementation. */
+#define ECORE_MERGESORT_LIMIT 40000
+
+/* Return information about the list */
+static void * _ecore_list_current(Ecore_List *list);
+
+/* Adding functions */
+static int _ecore_list_insert(Ecore_List *list,
+ Ecore_List_Node *node);
+static int _ecore_list_append_0(Ecore_List *list,
+ Ecore_List_Node *node);
+static int _ecore_list_prepend_0(Ecore_List *list,
+ Ecore_List_Node *node);
+
+/* Remove functions */
+static void * _ecore_list_remove_0(Ecore_List *list);
+static void * _ecore_list_first_remove(Ecore_List *list);
+static void * _ecore_list_last_remove(Ecore_List *list);
+
+/* Basic traversal functions */
+static void * _ecore_list_next(Ecore_List *list);
+static void * _ecore_list_last_goto(Ecore_List *list);
+static void * _ecore_list_first_goto(Ecore_List *list);
+static void * _ecore_list_goto(Ecore_List *list, const void *data);
+static void * _ecore_list_index_goto(Ecore_List *list, int idx);
+
+/* Iterative functions */
+static int _ecore_list_for_each(Ecore_List *list,
+ Ecore_For_Each function,
+ void *user_data);
+static void * _ecore_list_find(Ecore_List *list,
+ Ecore_Compare_Cb function,
+ const void *user_data);
+
+/* Sorting functions */
+static Ecore_List_Node *_ecore_list_node_mergesort(Ecore_List_Node *first,
+ int n,
+ Ecore_Compare_Cb compare,
+ int order);
+static Ecore_List_Node *_ecore_list_node_merge(Ecore_List_Node *first,
+ Ecore_List_Node *second,
+ Ecore_Compare_Cb compare,
+ int order);
+static Ecore_List_Node *_ecore_dlist_node_mergesort(Ecore_List_Node *first,
+ int n,
+ Ecore_Compare_Cb compare,
+ int order);
+static Ecore_List_Node *_ecore_dlist_node_merge(Ecore_List_Node *first,
+ Ecore_List_Node *second,
+ Ecore_Compare_Cb compare,
+ int order);
+
+/* Private double linked list functions */
+static void *_ecore_dlist_previous(Ecore_DList *list);
+static void *_ecore_dlist_first_remove(Ecore_DList *list);
+static void *_ecore_dlist_index_goto(Ecore_DList *list, int idx);
+
+/**
+ @defgroup Ecore_Data_List_Creation_Group List Creation/Destruction Functions
+
+ Functions that create, initialize and destroy Ecore_Lists.
+ */
+
+/**
+ * Create and initialize a new list.
+ * @return A new initialized list on success, @c NULL on failure.
+ * @ingroup Ecore_Data_List_Creation_Group
+ */
+EAPI Ecore_List *
+ecore_list_new(void)
+{
+ Ecore_List *list;
+
+ list = (Ecore_List *)malloc(sizeof(Ecore_List));
+ if (!list)
+ return NULL;
+
+ if (!ecore_list_init(list))
+ {
+ FREE(list);
+ return NULL;
+ }
+
+ return list;
+}
+
+/**
+ * Initialize a list to some sane starting values.
+ * @param list The list to initialize.
+ * @return @c TRUE if successful, @c FALSE if an error occurs.
+ * @ingroup Ecore_Data_List_Creation_Group
+ */
+EAPI int
+ecore_list_init(Ecore_List *list)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ memset(list, 0, sizeof(Ecore_List));
+
+ return TRUE;
+}
+
+/**
+ * Free a list and all of it's nodes.
+ * @param list The list to be freed.
+ * @ingroup Ecore_Data_List_Creation_Group
+ */
+EAPI void
+ecore_list_destroy(Ecore_List *list)
+{
+ void *data;
+
+ CHECK_PARAM_POINTER("list", list);
+
+ while (list->first)
+ {
+ data = _ecore_list_first_remove(list);
+ if (list->free_func)
+ list->free_func(data);
+ }
+
+ FREE(list);
+}
+
+/**
+ * Set the function for freeing data.
+ * @param list The list that will use this function when nodes are
+ * destroyed.
+ * @param free_func The function that will free the key data.
+ * @return @c TRUE on successful set, @c FALSE otherwise.
+ */
+EAPI int
+ecore_list_free_cb_set(Ecore_List *list, Ecore_Free_Cb free_func)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ list->free_func = free_func;
+
+ return TRUE;
+}
+
+/**
+ * Checks the list for any nodes.
+ * @param list The list to check for nodes
+ * @return @c TRUE if no nodes in list, @c FALSE if the list contains nodes
+ */
+EAPI int
+ecore_list_empty_is(Ecore_List *list)
+{
+ int ret = TRUE;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, TRUE);
+
+ if (list->nodes)
+ ret = FALSE;
+
+ return ret;
+}
+
+/**
+ * Returns the number of the current node.
+ * @param list The list to return the number of the current node.
+ * @return The number of the current node in the list.
+ */
+EAPI int
+ecore_list_index(Ecore_List *list)
+{
+ int ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ ret = list->index;
+
+ return ret;
+}
+
+/**
+ * Find the number of nodes in the list.
+ * @param list The list to find the number of nodes
+ * @return The number of nodes in the list.
+ */
+EAPI int
+ecore_list_count(Ecore_List *list)
+{
+ int ret = 0;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ ret = list->nodes;
+
+ return ret;
+}
+
+/**
+ @defgroup Ecore_Data_List_Add_Item_Group List Item Adding Functions
+
+ Functions that are used to add nodes to an Ecore_List.
+ */
+
+/**
+ * Append data to the list.
+ * @param list The list.
+ * @param data The data to append.
+ * @return @c FALSE if an error occurs, @c TRUE if appended successfully
+ * @ingroup Ecore_Data_List_Add_Item_Group
+ */
+EAPI inline int
+ecore_list_append(Ecore_List *list, void *data)
+{
+ int ret;
+ Ecore_List_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ node = ecore_list_node_new();
+ node->data = data;
+
+ ret = _ecore_list_append_0(list, node);
+
+ return ret;
+}
+
+/* For adding items to the end of the list */
+static int
+_ecore_list_append_0(Ecore_List *list, Ecore_List_Node *end)
+{
+ if (list->last)
+ list->last->next = end;
+
+ list->last = end;
+
+ if (!list->first)
+ {
+ list->first = end;
+ list->index = 0;
+ list->current = NULL;
+ }
+
+ if (list->index >= list->nodes)
+ list->index++;
+
+ list->nodes++;
+
+ return TRUE;
+}
+
+/**
+ * Prepend data to the beginning of the list.
+ * @param list The list.
+ * @param data The data to prepend.
+ * @return @c FALSE if an error occurs, @c TRUE if prepended successfully.
+ * @ingroup Ecore_Data_List_Add_Item_Group
+ */
+EAPI inline int
+ecore_list_prepend(Ecore_List *list, void *data)
+{
+ int ret;
+ Ecore_List_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ node = ecore_list_node_new();
+ node->data = data;
+
+ ret = _ecore_list_prepend_0(list, node);
+
+ return ret;
+}
+
+/* For adding items to the beginning of the list */
+static int
+_ecore_list_prepend_0(Ecore_List *list, Ecore_List_Node *start)
+{
+ /* Put it at the beginning of the list */
+ start->next = list->first;
+
+ list->first = start;
+
+ /* If no last node, then the first node is the last node */
+ if (!list->last)
+ list->last = list->first;
+
+ list->nodes++;
+ list->index++;
+
+ return TRUE;
+}
+
+/**
+ * Insert data in front of the current point in the list.
+ * @param list The list to hold the inserted @p data.
+ * @param data The data to insert into @p list.
+ * @return @c FALSE if there is an error, @c TRUE on success
+ * @ingroup Ecore_Data_List_Add_Item_Group
+ */
+EAPI inline int
+ecore_list_insert(Ecore_List *list, void *data)
+{
+ int ret;
+ Ecore_List_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ node = ecore_list_node_new();
+ node->data = data;
+
+ ret = _ecore_list_insert(list, node);
+
+ return ret;
+}
+
+/* For adding items in front of the current position in the list */
+static int
+_ecore_list_insert(Ecore_List *list, Ecore_List_Node *new_node)
+{
+ /*
+ * If the current point is at the beginning of the list, then it's the
+ * same as prepending it to the list.
+ */
+ if (list->current == list->first)
+ return _ecore_list_prepend_0(list, new_node);
+
+ if (!list->current)
+ {
+ int ret_value;
+
+ ret_value = _ecore_list_append_0(list, new_node);
+ list->current = list->last;
+
+ return ret_value;
+ }
+
+ /* Setup the fields of the new node */
+ new_node->next = list->current;
+
+ /* And hook the node into the list */
+ _ecore_list_index_goto(list, ecore_list_index(list) - 1);
+
+ list->current->next = new_node;
+
+ /* Now move the current item to the inserted item */
+ list->current = new_node;
+ list->nodes++;
+
+ return TRUE;
+}
+/**
+ * Append a list to the list.
+ * @param list The list.
+ * @param append The list to append.
+ * @return @c FALSE if an error occurs, @c TRUE if appended successfully
+ * @ingroup Ecore_Data_List_Add_Item_Group
+ */
+
+EAPI int
+ecore_list_append_list(Ecore_List *list, Ecore_List *append)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+ CHECK_PARAM_POINTER_RETURN("append", append, FALSE);
+
+ if (ecore_list_empty_is(append))
+ return TRUE;
+
+ if (ecore_list_empty_is(list))
+ {
+ list->first = append->first;
+ list->current = list->first;
+ list->last = append->last;
+ list->nodes = append->nodes;
+ }
+ else
+ {
+ list->last->next = append->first;
+ list->last = append->last;
+ list->nodes += append->nodes;
+ }
+
+ ecore_list_init(append);
+ return TRUE;
+}
+
+/**
+ * Prepend a list to the beginning of the list.
+ * @param list The list.
+ * @param prepend The list to prepend.
+ * @return @c FALSE if an error occurs, @c TRUE if prepended successfully.
+ * @ingroup Ecore_Data_List_Add_Item_Group
+ */
+EAPI int
+ecore_list_prepend_list(Ecore_List *list, Ecore_List *prepend)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+ CHECK_PARAM_POINTER_RETURN("prepend", prepend, FALSE);
+
+ if (ecore_list_empty_is(prepend))
+ return TRUE;
+
+ if (ecore_list_empty_is(list))
+ {
+ list->first = prepend->first;
+ list->current = NULL;
+ list->last = prepend->last;
+ list->nodes = prepend->nodes;
+ }
+ else
+ {
+ prepend->last->next = list->first;
+ list->first = prepend->first;
+ list->nodes += prepend->nodes;
+ list->index += prepend->nodes;
+ }
+
+ ecore_list_init(prepend);
+ return TRUE;
+}
+
+/**
+ @defgroup Ecore_Data_List_Remove_Item_Group List Item Removing Functions
+
+ Functions that remove nodes from an Ecore_List.
+ */
+
+/**
+ * Remove the current item from the list.
+ * @param list The list to remove the current item
+ * @return A pointer to the removed data on success, @c NULL on failure.
+ * @ingroup Ecore_Data_List_Remove_Item_Group
+ */
+EAPI inline void *
+ecore_list_remove(Ecore_List *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_remove_0(list);
+
+ return ret;
+}
+
+/* Remove the current item from the list */
+static void *
+_ecore_list_remove_0(Ecore_List *list)
+{
+ void *ret = NULL;
+ Ecore_List_Node *old;
+
+ if (!list)
+ return NULL;
+
+ if (ecore_list_empty_is(list))
+ return NULL;
+
+ if (!list->current)
+ return NULL;
+
+ if (list->current == list->first)
+ return _ecore_list_first_remove(list);
+
+ if (list->current == list->last)
+ return _ecore_list_last_remove(list);
+
+ old = list->current;
+
+ _ecore_list_index_goto(list, list->index - 1);
+
+ list->current->next = old->next;
+ old->next = NULL;
+ ret = old->data;
+ old->data = NULL;
+
+ _ecore_list_next(list);
+
+ ecore_list_node_destroy(old, NULL);
+ list->nodes--;
+
+ return ret;
+}
+
+/**
+ * Remove and free the data in lists current position.
+ * @param list The list to remove and free the current item.
+ * @return @c TRUE on success, @c FALSE on error
+ * @ingroup Ecore_Data_List_Remove_Item_Group
+ */
+EAPI int
+ecore_list_remove_destroy(Ecore_List *list)
+{
+ void *data;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ data = _ecore_list_remove_0(list);
+ if (list->free_func)
+ list->free_func(data);
+
+ return TRUE;
+}
+
+/**
+ * Remove the first item from the list.
+ * @param list The list to remove the current item
+ * @return Returns a pointer to the removed data on success, @c NULL on
+ * failure.
+ * @ingroup Ecore_Data_List_Remove_Item_Group
+ */
+EAPI inline void *
+ecore_list_first_remove(Ecore_List *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_first_remove(list);
+
+ return ret;
+}
+
+/* Remove the first item from the list */
+static void *
+_ecore_list_first_remove(Ecore_List *list)
+{
+ void *ret = NULL;
+ Ecore_List_Node *old;
+
+ if (!list)
+ return NULL;
+
+ if (ecore_list_empty_is(list))
+ return NULL;
+
+ old = list->first;
+
+ list->first = list->first->next;
+
+ if (list->current == old)
+ list->current = list->first;
+ else
+ (list->index ? list->index-- : 0);
+
+ if (list->last == old)
+ list->last = list->first;
+
+ ret = old->data;
+ old->data = NULL;
+
+ ecore_list_node_destroy(old, NULL);
+ list->nodes--;
+
+ return ret;
+}
+
+/**
+ * Remove the last item from the list.
+ * @param list The list to remove the last node from
+ * @return A pointer to the removed data on success, @c NULL on failure.
+ * @ingroup Ecore_Data_List_Remove_Item_Group
+ */
+EAPI inline void *
+ecore_list_last_remove(Ecore_List *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_last_remove(list);
+
+ return ret;
+}
+
+/* Remove the last item from the list */
+static void *
+_ecore_list_last_remove(Ecore_List *list)
+{
+ void *ret = NULL;
+ Ecore_List_Node *old, *prev;
+
+ if (!list)
+ return NULL;
+
+ if (ecore_list_empty_is(list))
+ return NULL;
+
+ old = list->last;
+ if (list->current == old)
+ list->current = NULL;
+
+ if (list->first == old)
+ list->first = NULL;
+
+ for (prev = list->first; prev && prev->next != old; prev = prev->next) ;
+ list->last = prev;
+ if (prev)
+ prev->next = NULL;
+
+ old->next = NULL;
+ ret = old->data;
+ old->data = NULL;
+
+ ecore_list_node_destroy(old, NULL);
+ list->nodes--;
+
+ return ret;
+}
+
+/**
+ @defgroup Ecore_Data_List_Traverse_Group List Traversal Functions
+
+ Functions that can be used to traverse an Ecore_List.
+ */
+
+/**
+ * Make the current item the item with the given index number.
+ * @param list The list.
+ * @param idx The position to move the current item.
+ * @return A pointer to new current item on success, @c NULL on failure.
+ * @ingroup Ecore_Data_List_Traverse_Group
+ */
+EAPI inline void *
+ecore_list_index_goto(Ecore_List *list, int idx)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_index_goto(list, idx);
+
+ return ret;
+}
+
+/* This is the non-threadsafe version, use this inside internal functions that
+ * already lock the list */
+static void *
+_ecore_list_index_goto(Ecore_List *list, int idx)
+{
+ int i;
+
+ if (!list)
+ return NULL;
+
+ if (ecore_list_empty_is(list))
+ return NULL;
+
+ if (idx > ecore_list_count(list) || idx < 0)
+ return NULL;
+
+ if (idx < list->index)
+ {
+ _ecore_list_first_goto(list);
+ i = 0;
+ }
+ else
+ i = list->index;
+
+ for (; i < idx && _ecore_list_next(list); i++) ;
+
+ if (i >= list->nodes)
+ return NULL;
+
+ list->index = i;
+
+ return list->current->data;
+}
+
+/**
+ * Make the current item the node that contains @p data.
+ * @param list The list.
+ * @param data The data to find.
+ * @return A pointer to @p data on success, @c NULL on failure.
+ * @ingroup Ecore_Data_List_Traverse_Group
+ */
+EAPI inline void *
+ecore_list_goto(Ecore_List *list, const void *data)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_goto(list, data);
+
+ return ret;
+}
+
+/* Set the current position to the node containing data */
+static void *
+_ecore_list_goto(Ecore_List *list, const void *data)
+{
+ int idx;
+ Ecore_List_Node *node;
+
+ if (!list)
+ return NULL;
+
+ idx = 0;
+
+ node = list->first;
+ while (node && node->data)
+ {
+ Ecore_List_Node *next;
+
+ if (node->data == data)
+ break;
+
+ next = node->next;
+
+ node = next;
+
+ idx++;
+ }
+
+ if (!node)
+ return NULL;
+
+ list->current = node;
+ list->index = idx;
+
+ return list->current->data;
+}
+
+/**
+ * Make the current item the first item in the list
+ * @param list The list.
+ * @return A pointer to the first item on success, @c NULL on failure
+ * @ingroup Ecore_Data_List_Traverse_Group
+ */
+EAPI inline void *
+ecore_list_first_goto(Ecore_List *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_first_goto(list);
+
+ return ret;
+}
+
+/* Set the current position to the start of the list */
+static void *
+_ecore_list_first_goto(Ecore_List *list)
+{
+ if (!list || !list->first)
+ return NULL;
+
+ list->current = list->first;
+ list->index = 0;
+
+ return list->current->data;
+}
+
+/**
+ * Make the current item the last item in the list.
+ * @param list The list.
+ * @return A pointer to the last item on success, @c NULL on failure.
+ * @ingroup Ecore_Data_List_Traverse_Group
+ */
+EAPI inline void *
+ecore_list_last_goto(Ecore_List *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_last_goto(list);
+
+ return ret;
+}
+
+/* Set the current position to the end of the list */
+static void *
+_ecore_list_last_goto(Ecore_List *list)
+{
+ if (!list || !list->last)
+ return NULL;
+
+ list->current = list->last;
+ list->index = (list->nodes - 1);
+
+ return list->current->data;
+}
+
+/**
+ * Retrieve the data pointed to by the current item in @p list.
+ * @param list The list.
+ * @return Returns the data at current position, can be @c NULL.
+ */
+EAPI inline void *
+ecore_list_current(Ecore_List *list)
+{
+ void *ret;
+
+ ret = _ecore_list_current(list);
+
+ return ret;
+}
+
+/**
+ * Retrieve the data pointed to by the first item in @p list.
+ * @param list The list.
+ * @return Returns the data at current position, can be @c NULL.
+ */
+EAPI inline void *
+ecore_list_first(Ecore_List *list)
+{
+ void *ret;
+
+ if (!list->first)
+ return NULL;
+
+ ret = list->first->data;
+
+ return ret;
+}
+
+/**
+ * Retrieve the data pointed to by the last item in @p list.
+ * @param list The list.
+ * @return Returns the data at current position, can be @c NULL.
+ */
+EAPI inline void *
+ecore_list_last(Ecore_List *list)
+{
+ void *ret;
+
+ if (!list->last)
+ return NULL;
+
+ ret = list->last->data;
+
+ return ret;
+}
+
+/* Return the data of the current node without incrementing */
+static void *
+_ecore_list_current(Ecore_List *list)
+{
+ void *ret;
+
+ if (!list->current)
+ return NULL;
+
+ ret = list->current->data;
+
+ return ret;
+}
+
+/**
+ * Retrieve the data pointed to by the current item, and make the next item
+ * the current item.
+ * @param list The list to retrieve data from.
+ * @return The current item in the list on success, @c NULL on failure.
+ */
+EAPI inline void *
+ecore_list_next(Ecore_List *list)
+{
+ void *data;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ data = _ecore_list_next(list);
+
+ return data;
+}
+
+/* Return the data contained in the current node and go to the next node */
+static void *
+_ecore_list_next(Ecore_List *list)
+{
+ void *data;
+ Ecore_List_Node *ret;
+ Ecore_List_Node *next;
+
+ if (!list->current)
+ return NULL;
+
+ ret = list->current;
+ next = list->current->next;
+
+ list->current = next;
+ list->index++;
+
+ data = ret->data;
+
+ return data;
+}
+
+/**
+ * Remove all nodes from @p list.
+ * @param list The list.
+ * @return Returns @c TRUE on success, @c FALSE on error.
+ * @note The data for each item on the list is not freed by
+ * @c ecore_list_clear().
+ */
+EAPI int
+ecore_list_clear(Ecore_List *list)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ while (!ecore_list_empty_is(list))
+ _ecore_list_first_remove(list);
+
+ return TRUE;
+}
+
+/**
+ * Execute function for each node in @p list.
+ * @param list The list.
+ * @param function The function to pass each node from @p list to.
+ * @return Returns @c TRUE on success, @c FALSE on failure.
+ * @ingroup Ecore_Data_List_Traverse_Group
+ */
+EAPI int
+ecore_list_for_each(Ecore_List *list, Ecore_For_Each function, void *user_data)
+{
+ int ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ ret = _ecore_list_for_each(list, function, user_data);
+
+ return ret;
+}
+
+/* The real meat of executing the function for each data node */
+static int
+_ecore_list_for_each(Ecore_List *list, Ecore_For_Each function, void *user_data)
+{
+ void *value;
+
+ if (!list || !function)
+ return FALSE;
+
+ _ecore_list_first_goto(list);
+ while ((value = _ecore_list_next(list)))
+ function(value, user_data);
+
+ return TRUE;
+}
+
+/**
+ * Find data in @p list using the compare function @p func
+ * @param list The list.
+ * @param function The function to test each node of @p list with
+ * @param user_data Data to match against (used by @p function)
+ * @return the first matching data node, or NULL if none match
+ */
+EAPI void *
+ecore_list_find(Ecore_List *list,
+ Ecore_Compare_Cb function,
+ const void *user_data)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ return _ecore_list_find(list, function, user_data);
+}
+
+/* The real meat of finding a node via a compare cb */
+static void *
+_ecore_list_find(Ecore_List *list,
+ Ecore_Compare_Cb function,
+ const void *user_data)
+{
+ void *value;
+ if (!list || !function)
+ return NULL;
+
+ _ecore_list_first_goto(list);
+ while ((value = _ecore_list_current(list)))
+ {
+ if (!function(value, user_data))
+ return value;
+
+ ecore_list_next(list);
+ }
+
+ return NULL;
+}
+
+/**
+ * Sort data in @p list using the compare function @p compare
+ * @param list The list.
+ * @param compare The function to compare the data of @p list
+ * @param order The sort direction, possible values are ECORE_SORT_MIN and
+ * ECORE_SORT_MAX
+ * @return true on success
+ *
+ * This is a wrapper function for mergesort and heapsort. It
+ * tries to choose the fastest algorithm depending on the
+ * number of notes. Note: The sort may be unstable.
+ */
+EAPI int
+ecore_list_sort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, 0);
+
+ if (list->nodes < 2)
+ return 1;
+
+ if (list->nodes < ECORE_MERGESORT_LIMIT)
+ return ecore_list_mergesort(list, compare, order);
+
+ if (!ecore_list_heapsort(list, compare, order))
+ return ecore_list_mergesort(list, compare, order);
+
+ return 1;
+}
+
+/**
+ * Sort data in @p list using the compare function @p compare
+ * @param list The list.
+ * @param compare The function to compare the data of @p list
+ * @param order The sort direction, possible values are ECORE_SORT_MIN and
+ * ECORE_SORT_MAX
+ * @return true on success
+ *
+ * Mergesort is a stable, in-place sorting algorithm
+ */
+EAPI int
+ecore_list_mergesort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
+{
+ Ecore_List_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, 0);
+ if (list->nodes < 2)
+ return 1;
+
+ if (order == ECORE_SORT_MIN)
+ order = 1;
+ else
+ order = -1;
+
+ node = _ecore_list_node_mergesort(list->first, list->nodes, compare, order);
+ list->first = node;
+
+ /* maybe there is a better way to do that but our last node has changed */
+ while (node->next)
+ node = node->next;
+ list->last = node;
+
+ _ecore_list_first_goto(list);
+
+ return 1;
+}
+
+/**
+ * Merge the @p l2 into the @p list using the compare function @p compare.
+ * Both lists need to be sorted else a corrupt list could be the result.
+ * @param list The list.
+ * @param l2 The second list, this list will be empty after the merge
+ * @param compare The function to compare the data of @p list and @p l2
+ * @param order The sort direction, possible values are ECORE_SORT_MIN and
+ * ECORE_SORT_MAX
+ */
+EAPI void
+ecore_list_merge(Ecore_List *list,
+ Ecore_List *l2,
+ Ecore_Compare_Cb compare,
+ char order)
+{
+ CHECK_PARAM_POINTER("list", list);
+ CHECK_PARAM_POINTER("l2", l2);
+
+ if (ecore_list_empty_is(l2))
+ return;
+
+ if (ecore_list_empty_is(list))
+ {
+ ecore_list_append_list(list, l2);
+ return;
+ }
+
+ if (order == ECORE_SORT_MIN)
+ order = 1;
+ else
+ order = -1;
+
+ list->first = _ecore_list_node_merge(list->first, l2->first, compare, order);
+
+ if ((order * compare(list->last->data, l2->last->data)) < 0)
+ list->last = l2->last;
+
+ list->nodes += l2->nodes;
+ ecore_list_init(l2);
+}
+
+/* this is the internal recrusive function for the merge sort */
+static Ecore_List_Node *
+_ecore_list_node_mergesort(Ecore_List_Node *first, int n,
+ Ecore_Compare_Cb compare, int order)
+{
+ Ecore_List_Node *middle;
+ Ecore_List_Node *premid;
+ int mid;
+ int i;
+
+ mid = n / 2;
+
+ if (n < 2)
+ return first;
+ else if (n == 2)
+ {
+ if (compare(first->data, first->next->data) * order > 0)
+ {
+ /* swap the data */
+ void *data;
+ data = first->next->data;
+ first->next->data = first->data;
+ first->data = data;
+ }
+
+ return first;
+ }
+
+ /* first find the premiddle node*/
+ for (premid = first, i = 0; i < mid - 1; i++)
+ premid = premid->next;
+
+ /* split the list */
+ middle = premid->next;
+ premid->next = NULL;
+
+ /* sort the the partial lists */
+ first = _ecore_list_node_mergesort(first, mid, compare, order);
+ middle = _ecore_list_node_mergesort(middle, n - mid, compare, order);
+
+ return _ecore_list_node_merge(first, middle, compare, order);
+}
+
+/* this function is used to merge the partial sorted lists */
+static Ecore_List_Node *
+_ecore_list_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
+ Ecore_Compare_Cb compare, int order)
+{
+ Ecore_List_Node *list;
+ Ecore_List_Node *l;
+
+ /* select the first node outside the loop, because we need to keep
+ * a pointer to it */
+ if (compare(first->data, second->data) * order > 0)
+ {
+ list = l = second;
+ second = second->next;
+ }
+ else
+ {
+ list = l = first;
+ first = first->next;
+ }
+
+ /* and now start the merging */
+ while (first && second)
+ {
+ if (compare(first->data, second->data) * order > 0)
+ {
+ l = l->next = second;
+ second = second->next;
+ }
+ else
+ {
+ l = l->next = first;
+ first = first->next;
+ }
+ }
+
+ /* append the rest or set it to NULL */
+ if (first)
+ l->next = first;
+ else if (second)
+ l->next = second;
+ else
+ l->next = NULL;
+
+ return list;
+}
+
+/**
+ * Sort data in @p list using the compare function @p compare
+ * @param list The list.
+ * @param compare The function to compare the data of @p list
+ * @param order The sort direction, possible values are ECORE_SORT_MIN and
+ * ECORE_SORT_MAX
+ * @return true on success
+ *
+ * Heapsort is a unstable sorting algorithm, it needs to allocate extra memomry,
+ * but there for it is for a great number of nodes faster than mergesort
+ */
+EAPI int
+ecore_list_heapsort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
+{
+ Ecore_Sheap *heap;
+ Ecore_List_Node *node;
+ void *data;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, 0);
+ /*
+ * Push the data into a heap.
+ */
+ heap = ecore_sheap_new(compare, list->nodes);
+ if (!heap)
+ return 0;
+
+ ecore_sheap_order_set(heap, order);
+ _ecore_list_first_goto(list);
+ while ((data = _ecore_list_next(list)))
+ {
+ ecore_sheap_insert(heap, data);
+ }
+
+ /*
+ * Extract in sorted order.
+ */
+ node = list->first;
+ while (node)
+ {
+ node->data = ecore_sheap_extract(heap);
+ node = node->next;
+ }
+
+ ecore_sheap_destroy(heap);
+
+ _ecore_list_first_goto(list);
+ return 1;
+}
+
+/* Initialize a node to starting values */
+EAPI int
+ecore_list_node_init(Ecore_List_Node *node)
+{
+ CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
+
+ node->next = NULL;
+ node->data = NULL;
+
+ return TRUE;
+}
+
+/**
+ @defgroup Ecore_Data_List_Node_Group List Node Functions
+
+ Functions that are used in the creation, maintenance and destruction of
+ Ecore_List nodes.
+ */
+
+/**
+ * Allocates and initializes a new list node.
+ * @return A new Ecore_List_Node on success, @c NULL otherwise.
+ * @ingroup Ecore_Data_List_Node_Group
+ */
+EAPI Ecore_List_Node *
+ecore_list_node_new()
+{
+ Ecore_List_Node *new_node;
+
+ new_node = malloc(sizeof(Ecore_List_Node));
+
+ if (!ecore_list_node_init(new_node))
+ {
+ FREE(new_node);
+ return NULL;
+ }
+
+ return new_node;
+}
+
+/**
+ * Calls the function to free the data and the node.
+ * @param node Node to destroy.
+ * @param free_func Function to call if @p node points to data to free.
+ * @return @c TRUE.
+ * @ingroup Ecore_Data_List_Node_Group
+ */
+EAPI int
+ecore_list_node_destroy(Ecore_List_Node *node, Ecore_Free_Cb free_func)
+{
+ CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
+
+ if (free_func && node->data)
+ free_func(node->data);
+
+ FREE(node);
+
+ return TRUE;
+}
+
+/**
+ * @defgroup Ecore_Data_DList_Creation_Group Doubly Linked List Creation/Destruction Functions
+ *
+ * Functions used to create, initialize and destroy @c Ecore_DLists.
+ */
+
+/**
+ * Creates and initialises a new doubly linked list.
+ * @return A new initialised doubly linked list on success, @c NULL
+ * on failure.
+ * @ingroup Ecore_Data_DList_Creation_Group
+ */
+EAPI Ecore_DList *
+ecore_dlist_new()
+{
+ Ecore_DList *list = NULL;
+
+ list = (Ecore_DList *)malloc(sizeof(Ecore_DList));
+ if (!list)
+ return NULL;
+
+ if (!ecore_dlist_init(list))
+ {
+ IF_FREE(list);
+ return NULL;
+ }
+
+ return list;
+}
+
+/**
+ * Initialises a list to some sane starting values.
+ * @param list The doubly linked list to initialise.
+ * @return @c TRUE if successful, @c FALSE if an error occurs.
+ * @ingroup Ecore_Data_DList_Creation_Group
+ */
+EAPI int
+ecore_dlist_init(Ecore_DList *list)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ memset(list, 0, sizeof(Ecore_DList));
+
+ return TRUE;
+}
+
+/**
+ * Frees a doubly linked list and all of its nodes.
+ * @param list The doubly linked list to be freed.
+ * @ingroup Ecore_Data_DList_Creation_Group
+ */
+EAPI void
+ecore_dlist_destroy(Ecore_DList *list)
+{
+ void *data;
+ CHECK_PARAM_POINTER("list", list);
+
+ while (list->first)
+ {
+ data = _ecore_dlist_first_remove(list);
+ if (list->free_func)
+ list->free_func(data);
+ }
+
+ FREE(list);
+}
+
+/**
+ * Sets the function used for freeing data stored in a doubly linked list.
+ * @param list The doubly linked list that will use this function when
+ * nodes are destroyed.
+ * @param free_func The function that will free the key data
+ * @return @c TRUE on success, @c FALSE on failure.
+ * @ingroup Ecore_Data_DList_Creation_Group
+ */
+EAPI int
+ecore_dlist_free_cb_set(Ecore_DList *list, Ecore_Free_Cb free_func)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ return ecore_list_free_cb_set(ECORE_LIST(list), free_func);
+}
+
+/**
+ * Returns whether there is anything in the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @return @c TRUE if there are nodes, @c FALSE otherwise.
+ */
+EAPI int
+ecore_dlist_empty_is(Ecore_DList *list)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ return ecore_list_empty_is(ECORE_LIST(list));
+}
+
+/**
+ * Retrieves the index of the current node of the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @return The index of the current node.
+ */
+EAPI inline int
+ecore_dlist_index(Ecore_DList *list)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ return ecore_list_index(ECORE_LIST(list));
+}
+
+/**
+ * @defgroup Ecore_Data_DList_Add_Item_Group Doubly Linked List Adding Functions
+ *
+ * Functions that are used to add nodes to an Ecore_DList.
+ */
+
+/**
+ * Appends data to the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @param data The data to append.
+ * @return @c TRUE if the data is successfully appended, @c FALSE otherwise.
+ * @ingroup Ecore_Data_DList_Add_Item_Group
+ */
+EAPI int
+ecore_dlist_append(Ecore_DList *list, void *data)
+{
+ int ret;
+ Ecore_DList_Node *prev;
+ Ecore_DList_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ node = ecore_dlist_node_new();
+ ECORE_LIST_NODE(node)->data = data;
+
+ prev = ECORE_DLIST_NODE(ECORE_LIST(list)->last);
+ ret = _ecore_list_append_0(ECORE_LIST(list), ECORE_LIST_NODE(node));
+ if (ret)
+ node->previous = prev;
+
+ return ret;
+}
+
+/**
+ * Adds data to the very beginning of the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @param data The data to prepend.
+ * @return @c TRUE if the data is successfully prepended, @c FALSE otherwise.
+ * @ingroup Ecore_Data_DList_Add_Item_Group
+ */
+EAPI int
+ecore_dlist_prepend(Ecore_DList *list, void *data)
+{
+ int ret;
+ Ecore_DList_Node *prev;
+ Ecore_DList_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ node = ecore_dlist_node_new();
+ ECORE_LIST_NODE(node)->data = data;
+
+ prev = ECORE_DLIST_NODE(ECORE_LIST(list)->first);
+ ret = _ecore_list_prepend_0(ECORE_LIST(list), ECORE_LIST_NODE(node));
+ if (ret && prev)
+ prev->previous = node;
+
+ return ret;
+}
+
+/**
+ * Inserts data at the current point in the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @param data The data to be inserted.
+ * @return @c TRUE on success, @c FALSE otherwise.
+ * @ingroup Ecore_Data_DList_Add_Item_Group
+ */
+EAPI int
+ecore_dlist_insert(Ecore_DList *list, void *data)
+{
+ int ret = TRUE;
+ Ecore_DList_Node *prev;
+ Ecore_DList_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ /*
+ * Identify and shortcut the end cases.
+ */
+ if (!ECORE_LIST(list)->current)
+ return ecore_dlist_append(list, data);
+
+ if (ECORE_LIST(list)->current == ECORE_LIST(list)->first)
+ return ecore_dlist_prepend(list, data);
+
+ node = ecore_dlist_node_new();
+ ECORE_LIST_NODE(node)->data = data;
+
+ /* Setup the fields of the new node */
+ ECORE_LIST_NODE(node)->next = ECORE_LIST(list)->current;
+
+ /* And hook the node into the list */
+ prev = ECORE_DLIST_NODE(ECORE_LIST(list)->current)->previous;
+ ECORE_LIST_NODE(prev)->next = ECORE_LIST_NODE(node);
+ ECORE_DLIST_NODE(ECORE_LIST(list)->current)->previous = node;
+ node->previous = prev;
+
+ /* Now move the current item to the inserted item */
+ ECORE_LIST(list)->current = ECORE_LIST_NODE(node);
+ ECORE_LIST(list)->nodes++;
+
+ return ret;
+}
+
+/**
+ * Appends a list to the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @param append The list to append.
+ * @return @c TRUE if the data is successfully appended, @c FALSE otherwise.
+ * @ingroup Ecore_Data_DList_Add_Item_Group
+ */
+EAPI int
+ecore_dlist_append_list(Ecore_DList *list, Ecore_DList *append)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+ CHECK_PARAM_POINTER_RETURN("append", append, FALSE);
+
+ if (ecore_dlist_empty_is(append))
+ return TRUE;
+
+ if (ecore_dlist_empty_is(list))
+ {
+ list->first = append->first;
+ list->current = NULL;
+ list->last = append->last;
+ list->nodes = append->nodes;
+ }
+ else
+ {
+ list->last->next = append->first;
+ ECORE_DLIST_NODE(append->first)->previous = ECORE_DLIST_NODE(list->last);
+ list->last = append->last;
+ list->nodes += append->nodes;
+ }
+
+ ecore_dlist_init(append);
+ return TRUE;
+}
+
+/**
+ * Adds a list to the very beginning of the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @param prepend The list to prepend.
+ * @return @c TRUE if the data is successfully prepended, @c FALSE otherwise.
+ * @ingroup Ecore_Data_DList_Add_Item_Group
+ */
+EAPI int
+ecore_dlist_prepend_list(Ecore_DList *list, Ecore_DList *prepend)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+ CHECK_PARAM_POINTER_RETURN("prepend", prepend, FALSE);
+
+ if (ecore_dlist_empty_is(prepend))
+ return TRUE;
+
+ if (ecore_dlist_empty_is(list))
+ {
+ list->first = prepend->first;
+ list->current = NULL;
+ list->last = prepend->last;
+ list->nodes = prepend->nodes;
+ }
+ else
+ {
+ prepend->last->next = list->first;
+ ECORE_DLIST_NODE(list->first)->previous = ECORE_DLIST_NODE(
+ prepend->last);
+ list->first = prepend->first;
+ list->nodes += prepend->nodes;
+ list->index += prepend->nodes;
+ }
+
+ ecore_dlist_init(prepend);
+ return TRUE;
+}
+
+/**
+ * @defgroup Ecore_Data_DList_Remove_Item_Group Doubly Linked List Removing Functions
+ *
+ * Functions that remove nodes from an @c Ecore_DList.
+ */
+
+/**
+ * Removes the current item from the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @return A pointer to the removed data on success, @c NULL otherwise.
+ * @ingroup Ecore_Data_DList_Remove_Item_Group
+ */
+EAPI void *
+ecore_dlist_remove(Ecore_DList *list)
+{
+ void *ret;
+ Ecore_List *l2 = ECORE_LIST(list);
+ Ecore_DList_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ if (l2->current)
+ {
+ node = ECORE_DLIST_NODE(list->current->next);
+ if (node)
+ node->previous = ECORE_DLIST_NODE(l2->current)->previous;
+ }
+
+ ret = _ecore_list_remove_0(list);
+
+ return ret;
+}
+
+/**
+ * Removes the first item from the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @return A pointer to the removed data on success, @c NULL on failure.
+ * @ingroup Ecore_Data_DList_Remove_Item_Group
+ */
+EAPI void *
+ecore_dlist_first_remove(Ecore_DList *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_dlist_first_remove(list);
+
+ return ret;
+}
+
+/**
+ * Removes and frees the data at the current position in the given doubly
+ * linked list.
+ * @param list The given doubly linked list.
+ * @return @c TRUE on success, @c FALSE otherwise.
+ * @ingroup Ecore_Data_DList_Remove_Item_Group
+ */
+EAPI int
+ecore_dlist_remove_destroy(Ecore_DList *list)
+{
+ void *data;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ data = ecore_dlist_remove(list);
+ if (!data)
+ return FALSE;
+
+ if (list->free_func)
+ list->free_func(data);
+
+ return TRUE;
+}
+
+static void *
+_ecore_dlist_first_remove(Ecore_DList *list)
+{
+ void *ret;
+
+ if (!list)
+ return NULL;
+
+ ret = _ecore_list_first_remove(list);
+ if (ret && ECORE_LIST(list)->first)
+ ECORE_DLIST_NODE(ECORE_LIST(list)->first)->previous = NULL;
+
+ return ret;
+}
+
+/**
+ * Removes the last item from the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @return A pointer to the removed data on success, @c NULL otherwise.
+ * @ingroup Ecore_Data_DList_Remove_Item_Group
+ */
+EAPI void *
+ecore_dlist_last_remove(Ecore_DList *list)
+{
+ void *ret;
+ Ecore_List_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ if (ecore_list_empty_is(list))
+ return NULL;
+
+ node = list->last;
+ list->last = ECORE_LIST_NODE(ECORE_DLIST_NODE(node)->previous);
+ if (list->last)
+ list->last->next = NULL;
+
+ if (list->first == node)
+ list->first = NULL;
+
+ if (list->current == node)
+ list->current = NULL;
+
+ ret = node->data;
+ ecore_list_node_destroy(node, NULL);
+
+ list->nodes--;
+ if (list->index >= list->nodes)
+ list->index--;
+
+ return ret;
+}
+
+/**
+ * Moves the current item to the index number in the given doubly linked list.
+ * @param list The given doubly linked list.
+ * @param idx The position to move the current item
+ * @return The node at specified index on success, @c NULL on error.
+ */
+EAPI void *
+ecore_dlist_index_goto(Ecore_DList *list, int idx)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_dlist_index_goto(list, idx);
+
+ return ret;
+}
+
+/* This is the non-threadsafe version, use this inside internal functions that
+ * already lock the list */
+static void *
+_ecore_dlist_index_goto(Ecore_DList *list, int idx)
+{
+ int i, increment;
+
+ if (!list)
+ return NULL;
+
+ if (ecore_list_empty_is(ECORE_LIST(list)))
+ return NULL;
+
+ if (idx > ecore_list_count(ECORE_LIST(list)) || idx < 0)
+ return NULL;
+
+ if (ECORE_LIST(list)->index >= ECORE_LIST(list)->nodes)
+ _ecore_list_last_goto(ECORE_LIST(list));
+
+ if (idx < ECORE_LIST(list)->index)
+ increment = -1;
+ else
+ increment = 1;
+
+ for (i = ECORE_LIST(list)->index; i != idx; i += increment)
+ {
+ if (increment > 0)
+ _ecore_list_next(list);
+ else
+ _ecore_dlist_previous(list);
+ }
+
+ return _ecore_list_current(list);
+}
+
+/**
+ * @brief Move the current item to the node that contains data
+ * @param list: the list to move the current item in
+ * @param data: the data to find and set the current item to
+ *
+ * @return Returns specified data on success, NULL on error
+ */
+EAPI void *
+ecore_dlist_goto(Ecore_DList *list, void *data)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_goto(ECORE_LIST(list), data);
+
+ return ret;
+}
+
+/**
+ * @brief Move the current pointer to the first item in the list
+ * @param list: the list to change the current to the first item
+ *
+ * @return Returns a pointer to the first item on success, NULL on failure.
+ */
+EAPI void *
+ecore_dlist_first_goto(Ecore_DList *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_first_goto(list);
+
+ return ret;
+}
+
+/**
+ * @brief Move the pointer to the current item to the last item
+ * @param list: the list to move the current item pointer to the last
+ * @return Returns a pointer to the last item in the list , NULL if empty.
+ */
+EAPI void *
+ecore_dlist_last_goto(Ecore_DList *list)
+{
+ void *ret;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, NULL);
+
+ ret = _ecore_list_last_goto(ECORE_LIST(list));
+
+ return ret;
+}
+
+/**
+ * @brief Return the data in the current list item
+ * @param list: the list to the return the current data
+ * @return Returns value of the current data item, NULL if no current item
+ */
+EAPI void *
+ecore_dlist_current(Ecore_DList *list)
+{
+ void *ret;
+
+ ret = _ecore_list_current(ECORE_LIST(list));
+
+ return ret;
+}
+
+/**
+ * @brief Move to the next item in the list and return current item
+ * @param list: the list to move to the next item in.
+ * @return Returns data in the current list node, or NULL on error
+ */
+EAPI void *
+ecore_dlist_next(Ecore_DList *list)
+{
+ void *data;
+
+ data = _ecore_list_next(list);
+
+ return data;
+}
+
+/**
+ * @brief Move to the previous item and return current item
+ * @param list: the list to move to the previous item in.
+ * @return Returns data in the current list node, or NULL on error
+ */
+EAPI void *
+ecore_dlist_previous(Ecore_DList *list)
+{
+ void *data;
+
+ data = _ecore_dlist_previous(list);
+
+ return data;
+}
+
+static void *
+_ecore_dlist_previous(Ecore_DList *list)
+{
+ void *data = NULL;
+
+ if (!list)
+ return NULL;
+
+ if (ECORE_LIST(list)->current)
+ {
+ data = ECORE_LIST(list)->current->data;
+ ECORE_LIST(list)->
+ current = ECORE_LIST_NODE(ECORE_DLIST_NODE(
+ ECORE_LIST(list)->
+ current)->previous);
+ ECORE_LIST(list)->index
+ --;
+ }
+ else
+ _ecore_list_last_goto(
+ ECORE_LIST(list));
+
+ return data;
+}
+
+/**
+ * @brief Remove all nodes from the list.
+ * @param list: the list to remove all nodes from
+ *
+ * @return Returns TRUE on success, FALSE on errors
+ */
+EAPI int
+ecore_dlist_clear(Ecore_DList *list)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
+
+ ecore_list_clear(ECORE_LIST(list));
+
+ return TRUE;
+}
+
+/**
+ * Sort data in @p list using the compare function @p compare
+ * @param list The list.
+ * @param compare The function to compare the data of @p list
+ * @param order The sort direction, possible values are ECORE_SORT_MIN and
+ * ECORE_SORT_MAX
+ * @return true on success
+ *
+ * This is a wrapper function for mergesort and heapsort. It
+ * tries to choose the fastest algorithm depending on the
+ * number of notes. Note: The sort may be unstable.
+ */
+EAPI int
+ecore_dlist_sort(Ecore_List *list, Ecore_Compare_Cb compare, char order)
+{
+ CHECK_PARAM_POINTER_RETURN("list", list, 0);
+
+ if (list->nodes < 2)
+ return 1;
+
+ if (list->nodes < ECORE_MERGESORT_LIMIT)
+ return ecore_dlist_mergesort(list, compare, order);
+
+ if (!ecore_dlist_heapsort(list, compare, order))
+ return ecore_dlist_mergesort(list, compare, order);
+
+ return 1;
+}
+
+/**
+ * Sort data in @p list using the compare function @p compare
+ * @param list The list.
+ * @param compare The function to compare the data of @p list
+ * @param order The sort direction, possible values are ECORE_SORT_MIN and
+ * ECORE_SORT_MAX
+ * @return true on success
+ *
+ * Mergesort is a stable, in-place sorting algorithm
+ */
+EAPI int
+ecore_dlist_mergesort(Ecore_DList *list, Ecore_Compare_Cb compare, char order)
+{
+ Ecore_List_Node *node;
+
+ CHECK_PARAM_POINTER_RETURN("list", list, 0);
+ if (list->nodes < 2)
+ return 1;
+
+ if (order == ECORE_SORT_MIN)
+ order = 1;
+ else
+ order = -1;
+
+ node = _ecore_dlist_node_mergesort(list->first, list->nodes, compare, order);
+ list->first = node;
+
+ /* maybe there is a better way to do that but our last node has changed */
+ while (node->next)
+ node = node->next;
+ list->last = node;
+
+ _ecore_list_first_goto(list);
+
+ return 1;
+}
+
+/**
+ * Merge the @p l2 into the @p list using the compare function @p compare.
+ * Both lists need to be sorted else a corrupt list could be the result.
+ * @param list The list.
+ * @param l2 The second list, this list will be empty after the merge
+ * @param compare The function to compare the data of @p list and @p l2
+ * @param order The sort direction, possible values are ECORE_SORT_MIN and
+ * ECORE_SORT_MAX
+ */
+EAPI void
+ecore_dlist_merge(Ecore_DList *list,
+ Ecore_DList *l2,
+ Ecore_Compare_Cb compare,
+ char order)
+{
+ CHECK_PARAM_POINTER("list", list);
+ CHECK_PARAM_POINTER("l2", l2);
+
+ if (ecore_dlist_empty_is(l2))
+ return;
+
+ if (ecore_dlist_empty_is(list))
+ {
+ ecore_dlist_append_list(list, l2);
+ return;
+ }
+
+ if (order == ECORE_SORT_MIN)
+ order = 1;
+ else
+ order = -1;
+
+ list->first = _ecore_dlist_node_merge(list->first, l2->first, compare, order);
+
+ if ((order * compare(list->last->data, l2->last->data)) < 0)
+ list->last = l2->last;
+
+ list->nodes += l2->nodes;
+ ecore_dlist_init(l2);
+}
+
+/* this is the internal recrusive function for the merge sort */
+static Ecore_List_Node *
+_ecore_dlist_node_mergesort(Ecore_List_Node *first, int n,
+ Ecore_Compare_Cb compare, int order)
+{
+ Ecore_List_Node *middle;
+ Ecore_List_Node *premid;
+ int mid;
+ int i;
+
+ mid = n / 2;
+
+ if (n < 2)
+ return first;
+ else if (n == 2)
+ {
+ if (compare(first->data, first->next->data) * order > 0)
+ {
+ /* swap the data */
+ void *data;
+ data = first->next->data;
+ first->next->data = first->data;
+ first->data = data;
+ }
+
+ return first;
+ }
+
+ /* first find the premiddle node*/
+ for (premid = first, i = 0; i < mid - 1; i++)
+ premid = premid->next;
+
+ /* split the list */
+ middle = premid->next;
+ premid->next = NULL;
+ ECORE_DLIST_NODE(middle)->previous = NULL;
+
+ /* sort the the partial lists */
+ first = _ecore_dlist_node_mergesort(first, mid, compare, order);
+ middle = _ecore_dlist_node_mergesort(middle, n - mid, compare, order);
+
+ return _ecore_dlist_node_merge(first, middle, compare, order);
+}
+
+/* this function is used to merge the partial sorted lists */
+static Ecore_List_Node *
+_ecore_dlist_node_merge(Ecore_List_Node *first, Ecore_List_Node *second,
+ Ecore_Compare_Cb compare, int order)
+{
+ Ecore_List_Node *list;
+ Ecore_List_Node *l;
+
+ /* select the first node outside the loop, because we need to keep
+ * a pointer to it */
+ if (compare(first->data, second->data) * order > 0)
+ {
+ list = l = second;
+ second = second->next;
+ }
+ else
+ {
+ list = l = first;
+ first = first->next;
+ }
+
+ /* and now start the merging */
+ while (first && second)
+ {
+ if (compare(first->data, second->data) * order > 0)
+ {
+ ECORE_DLIST_NODE(second)->previous = ECORE_DLIST_NODE(l);
+ l = l->next = second;
+ second = second->next;
+ }
+ else
+ {
+ ECORE_DLIST_NODE(first)->previous = ECORE_DLIST_NODE(l);
+ l = l->next = first;
+ first = first->next;
+ }
+ }
+
+ /* append the rest or set it to NULL */
+ if (first)
+ {
+ ECORE_DLIST_NODE(first)->previous = ECORE_DLIST_NODE(l);
+ l->next = first;
+ }
+ else if (second)
+ {
+ ECORE_DLIST_NODE(second)->previous = ECORE_DLIST_NODE(l);
+ l->next = second;
+ }
+ else
+ l->next = NULL;
+
+ return list;
+}
+
+/*
+ * @brief Initialize a node to sane starting values
+ * @param node: the node to initialize
+ * @return Returns TRUE on success, FALSE on errors
+ */
+EAPI int
+ecore_dlist_node_init(Ecore_DList_Node *node)
+{
+ int ret;
+
+ CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
+
+ ret = ecore_list_node_init(ECORE_LIST_NODE(node));
+ if (ret)
+ node->previous = NULL;
+
+ return ret;
+}
+
+/*
+ * @brief Allocate and initialize a new list node
+ * @return Returns NULL on error, new list node on success
+ */
+EAPI Ecore_DList_Node *
+ecore_dlist_node_new()
+{
+ Ecore_DList_Node *new_node;
+
+ new_node = malloc(sizeof(Ecore_DList_Node));
+
+ if (!new_node)
+ return NULL;
+
+ if (!ecore_dlist_node_init(new_node))
+ {
+ FREE(new_node);
+ return NULL;
+ }
+
+ return new_node;
+}
+
+/*
+ * @brief Call the data's free callback function, then free the node
+ * @param node: the node to be freed
+ * @param free_func: the callback function to execute on the data
+ * @return Returns TRUE on success, FALSE on error
+ */
+EAPI int
+ecore_dlist_node_destroy(Ecore_DList_Node *node, Ecore_Free_Cb free_func)
+{
+ CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
+
+ return ecore_list_node_destroy(ECORE_LIST_NODE(node), free_func);
+}
diff --git a/src/tests/eina/ecore_sheap.c b/src/tests/eina/ecore_sheap.c
new file mode 100644
index 000000000..448be9791
--- /dev/null
+++ b/src/tests/eina/ecore_sheap.c
@@ -0,0 +1,467 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "Ecore_Data.h"
+
+#define HEAP_INCREMENT 4096
+
+#define PARENT(i) (i / 2)
+#define LEFT(i) (2 * i)
+#define RIGHT(i) (2 * i + 1)
+
+static void _ecore_sheap_heapify(Ecore_Sheap *heap, int i);
+static void _ecore_sheap_update_data(Ecore_Sheap *heap);
+
+/**
+ * Allocate and initialize a new binary heap
+ * @param compare The function for comparing keys, NULL for direct comparison
+ * @param size The number of elements to allow in the heap
+ * @return A pointer to the newly allocated binary heap on success, NULL on
+ * failure.
+ */
+EAPI Ecore_Sheap *
+ecore_sheap_new(Ecore_Compare_Cb compare, int size)
+{
+ Ecore_Sheap *heap = NULL;
+
+ heap = (Ecore_Sheap *)malloc(sizeof(Ecore_Sheap));
+ if (!heap)
+ return NULL;
+
+ memset(heap, 0, sizeof(Ecore_Sheap));
+
+ if (!ecore_sheap_init(heap, compare, size))
+ {
+ FREE(heap);
+ return NULL;
+ }
+
+ return heap;
+}
+
+/**
+ * Initialize a binary heap to default values
+ * @param heap The heap to initialize
+ * @param compare The function for comparing keys, NULL for direct comparison
+ * @param size The number of elements to allow in the heap
+ * @return TRUE on success, FALSE on failure
+ */
+EAPI int
+ecore_sheap_init(Ecore_Sheap *heap, Ecore_Compare_Cb compare, int size)
+{
+ CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE);
+
+ heap->space = size;
+ if (!compare)
+ heap->compare = ecore_direct_compare;
+ else
+ heap->compare = compare;
+
+ heap->order = ECORE_SORT_MIN;
+
+ heap->data = (void **)malloc(heap->space * sizeof(void *));
+ if (!heap->data)
+ return FALSE;
+
+ memset(heap->data, 0, heap->space * sizeof(void *));
+
+ return TRUE;
+}
+
+/**
+ * Free up the memory used by the heap
+ *
+ * Frees the memory used by @a heap, calls the destroy function on each data
+ * item if necessary.
+ *
+ * @param heap The heap to be freed
+ */
+EAPI void
+ecore_sheap_destroy(Ecore_Sheap *heap)
+{
+ int i;
+
+ CHECK_PARAM_POINTER("heap", heap);
+
+ /*
+ * Free data in heap
+ */
+ if (heap->free_func)
+ for (i = 0; i < heap->size; i++)
+ heap->free_func(heap->data[i]);
+
+ FREE(heap->data);
+
+ FREE(heap);
+}
+
+/**
+ * Set the function for freeing data.
+ * @param heap The heap that will use this function when nodes are
+ * destroyed.
+ * @param free_func The function that will free the key data.
+ * @return @c TRUE on successful set, @c FALSE otherwise.
+ */
+EAPI int
+ecore_sheap_free_cb_set(Ecore_Sheap *heap, Ecore_Free_Cb free_func)
+{
+ CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE);
+
+ heap->free_func = free_func;
+
+ return TRUE;
+}
+
+/**
+ * Insert new data into the heap.
+ * @param heap The heap to insert @a data.
+ * @param data The data to add to @a heap.
+ * @return TRUE on success, NULL on failure. Increases the size of the heap if
+ * it becomes larger than available space.
+ */
+EAPI int
+ecore_sheap_insert(Ecore_Sheap *heap, void *data)
+{
+ int i;
+ void *temp;
+ int parent;
+ int position;
+
+ CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE);
+
+ /*
+ * Increase the size of the allocated data area if there isn't enough
+ * space available to add this data
+ */
+ if (heap->size >= heap->space)
+ return FALSE;
+
+ heap->sorted = FALSE;
+
+ /*
+ * Place the data at the end of the heap initially. Then determine the
+ * parent and position in the array of it's parent.
+ */
+ heap->data[heap->size] = data;
+ position = heap->size;
+ heap->size++;
+ i = heap->size;
+ parent = PARENT(i) - 1;
+
+ /*
+ * Check the order of the heap to decide where to place the inserted
+ * data. The loop is placed inside the if statement to reduce the
+ * number of branching decisions that must be predicted.
+ */
+ if (heap->order == ECORE_SORT_MIN)
+ while ((position > 0) && heap->compare(heap->data[parent],
+ heap->data[position]) > 0)
+ {
+
+ /*
+ * Swap the data with it's parents to move it up in
+ * the heap.
+ */
+ temp = heap->data[position];
+ heap->data[position] = heap->data[parent];
+ heap->data[parent] = temp;
+
+ /*
+ * Now determine the new position for the next
+ * iteration of the loop, as well as it's parents
+ * position.
+ */
+ i = PARENT(i);
+ position = i - 1;
+ parent = PARENT(i) - 1;
+ }
+ else
+ while ((position > 0) && heap->compare(heap->data[parent],
+ heap->data[position]) < 0)
+ {
+
+ /*
+ * Swap the data with it's parents to move it up in
+ * the heap.
+ */
+ temp = heap->data[position];
+ heap->data[position] = heap->data[PARENT(i) - 1];
+ heap->data[PARENT(i) - 1] = temp;
+
+ /*
+ * Now determine the new position for the next
+ * iteration of the loop, as well as it's parents
+ * position.
+ */
+ i = PARENT(i);
+ position = i - 1;
+ parent = PARENT(i) - 1;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Extract the item at the top of the heap
+ * @param heap The heap to remove the top item
+ * @return The top item of the heap on success, NULL on failure.
+ * @note The extract function maintains the heap properties after the
+ * extract.
+ */
+EAPI void *
+ecore_sheap_extract(Ecore_Sheap *heap)
+{
+ void *extreme;
+
+ if (heap->size < 1)
+ return NULL;
+
+ heap->sorted = FALSE;
+
+ extreme = heap->data[0];
+ heap->size--;
+ heap->data[0] = heap->data[heap->size];
+
+ _ecore_sheap_heapify(heap, 1);
+
+ return extreme;
+}
+
+/**
+ * Examine the item at the top of the heap
+ * @param heap The heap to examine the top item
+ * @return The top item of the heap on success, NULL on failure.
+ * @note The function does not alter the heap.
+ */
+EAPI void *
+ecore_sheap_extreme(Ecore_Sheap *heap)
+{
+ if (heap->size < 1)
+ return NULL;
+
+ return heap->data[0];
+}
+
+/**
+ * Change the value of the specified item in the heap
+ * @param heap The heap to search for the item to change
+ * @param item The item in the heap to change
+ * @param newval The new value assigned to the item in the heap
+ * @return TRUE on success, FALSE on failure.
+ * @note The heap does not free the old data since it must be passed
+ * in, so the caller can perform the free if desired.
+ */
+EAPI int
+ecore_sheap_change(Ecore_Sheap *heap, void *item, void *newval)
+{
+ int i;
+
+ CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE);
+
+ for (i = 0; i < heap->size && heap->compare(heap->data[i], item); i++) ;
+
+ if (i < heap->size)
+ heap->data[i] = newval;
+ else
+ return FALSE;
+
+ /*
+ * FIXME: This is not the correct procedure when a change occurs.
+ */
+ _ecore_sheap_heapify(heap, 1);
+
+ return TRUE;
+}
+
+/**
+ * Change the comparison function for the heap
+ * @param heap The heap to change comparison function
+ * @param compare The new function for comparing nodes
+ * @return TRUE on success, FALSE on failure.
+ *
+ * The comparison function is changed to @compare and the heap is heapified
+ * by the new comparison.
+ */
+EAPI int
+ecore_sheap_compare_set(Ecore_Sheap *heap, Ecore_Compare_Cb compare)
+{
+ CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE);
+
+ if (!compare)
+ heap->compare = ecore_direct_compare;
+ else
+ heap->compare = compare;
+
+ _ecore_sheap_update_data(heap);
+
+ return TRUE;
+}
+
+/**
+ * Change the order of the heap
+ * @param heap The heap to change the order
+ * @param order The new order of the heap
+ *
+ * Changes the heap order of @heap and re-heapifies the data to this new
+ * order. The default order is a min heap.
+ */
+EAPI void
+ecore_sheap_order_set(Ecore_Sheap *heap, char order)
+{
+ CHECK_PARAM_POINTER("heap", heap);
+
+ heap->order = order;
+
+ _ecore_sheap_update_data(heap);
+}
+
+/**
+ * Sort the data in the heap
+ * @param heap The heap to be sorted
+ *
+ * Sorts the data in the heap into the order that is used for the heap's
+ * data.
+ */
+EAPI void
+ecore_sheap_sort(Ecore_Sheap *heap)
+{
+ int i = 0;
+ void **new_data;
+
+ CHECK_PARAM_POINTER("heap", heap);
+
+ new_data = (void **)malloc(heap->size * sizeof(void *));
+
+ /*
+ * Extract the heap and insert into the new data array in order.
+ */
+ while (heap->size > 0)
+ new_data[i++] = ecore_sheap_extract(heap);
+
+ /*
+ * Free the old data array and update the heap with the new data, also
+ * mark as sorted.
+ */
+ FREE(heap->data);
+ heap->data = new_data;
+ heap->size = i;
+ heap->sorted = TRUE;
+}
+
+/*
+ * Access the item at the ith position in the heap
+ * @param heap The heap to access the internal data
+ * @param i The index of the data within the heap
+ * @return The data located at the ith position within @heap on success,
+ * NULL on failure.
+ * @note The data is guaranteed to be in sorted order.
+ */
+EAPI inline void *
+ecore_sheap_item(Ecore_Sheap *heap, int i)
+{
+ if (i >= heap->size)
+ return NULL;
+
+ /*
+ * Make sure the data is sorted so we return the correct value.
+ */
+ if (!heap->sorted)
+ ecore_sheap_sort(heap);
+
+ return heap->data[i];
+}
+
+/*
+ * Regain the heap properties starting at position i
+ * @param heap The heap to regain heap properties
+ * @param i The position to start heapifying
+ */
+static void
+_ecore_sheap_heapify(Ecore_Sheap *heap, int i)
+{
+ int extreme;
+ int left = LEFT(i);
+ int right = RIGHT(i);
+
+ if (heap->order == ECORE_SORT_MIN)
+ {
+ if (left <= heap->size && heap->compare(heap->data[left - 1],
+ heap->data[i - 1]) < 0)
+ extreme = left;
+ else
+ extreme = i;
+
+ if (right <= heap->size && heap->compare(heap->data[right - 1],
+ heap->data[extreme - 1]) < 0)
+ extreme = right;
+ }
+ else
+ {
+ if (left <= heap->size && heap->compare(heap->data[left - 1],
+ heap->data[i - 1]) > 0)
+ extreme = left;
+ else
+ extreme = i;
+
+ if (right <= heap->size && heap->compare(heap->data[right - 1],
+ heap->data[extreme - 1]) > 0)
+ extreme = right;
+ }
+
+ /*
+ * If the data needs to be swapped down the heap, recurse on
+ * heapifying it's new placement.
+ */
+ if (extreme != i)
+ {
+ void *temp;
+
+ temp = heap->data[extreme - 1];
+ heap->data[extreme - 1] = heap->data[i - 1];
+ heap->data[i - 1] = temp;
+
+ _ecore_sheap_heapify(heap, extreme);
+ }
+}
+
+static void
+_ecore_sheap_update_data(Ecore_Sheap *heap)
+{
+ int i, old_size;
+ void **data;
+
+ /*
+ * Track the old values from the heap
+ */
+ old_size = heap->size;
+ data = heap->data;
+
+ heap->size = 0;
+ heap->data = malloc(heap->space * sizeof(void *));
+
+ for (i = 0; i < old_size; i++)
+ ecore_sheap_insert(heap, data[i]);
+
+ FREE(data);
+}
+
+int
+ecore_direct_compare(const void *key1, const void *key2)
+{
+ unsigned long k1, k2;
+
+ k1 = (unsigned long)key1;
+ k2 = (unsigned long)key2;
+
+ if (k1 > k2)
+ return 1;
+
+ if (k1 < k2)
+ return -1;
+
+ return 0;
+}
diff --git a/src/tests/eina/ecore_strings.c b/src/tests/eina/ecore_strings.c
new file mode 100644
index 000000000..d76e4c5f5
--- /dev/null
+++ b/src/tests/eina/ecore_strings.c
@@ -0,0 +1,160 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "Ecore_Data.h"
+
+static void ecore_string_free_cb(void *data);
+
+static Ecore_Hash *ecore_strings = NULL;
+static int ecore_string_init_count = 0;
+
+/**
+ * @defgroup Ecore_String_Group String Instance Functions
+ *
+ * These functions allow you to store one copy of a string, and use it
+ * throughout your program.
+ *
+ * This is a method to reduce the number of duplicated strings kept in
+ * memory. It's pretty common for the same strings to be dynamically
+ * allocated repeatedly between applications and libraries, especially in
+ * circumstances where you could have multiple copies of a structure that
+ * allocates the string. So rather than duplicating and freeing these
+ * strings, you request a read-only pointer to an existing string and
+ * only incur the overhead of a hash lookup.
+ *
+ * It sounds like micro-optimizing, but profiling has shown this can have
+ * a significant impact as you scale the number of copies up. It improves
+ * string creation/destruction speed, reduces memory use and decreases
+ * memory fragmentation, so a win all-around.
+ */
+
+/**
+ * Initialize the ecore string internal structure.
+ * @return Zero on failure, non-zero on successful initialization.
+ */
+EAPI int
+ecore_string_init()
+{
+ /*
+ * No strings have been loaded at this point, so create the hash
+ * table for storing string info for later.
+ */
+ if (!ecore_string_init_count)
+ {
+ ecore_strings = ecore_hash_new(ecore_str_hash, ecore_str_compare);
+ if (!ecore_strings)
+ return 0;
+
+ ecore_hash_free_value_cb_set(ecore_strings, ecore_string_free_cb);
+ }
+
+ ecore_string_init_count++;
+
+ return 1;
+}
+
+/**
+ * Retrieves an instance of a string for use in an ecore program.
+ * @param string The string to retrieve an instance of.
+ * @return A pointer to an instance of the string on success.
+ * @c NULL on failure.
+ * @ingroup Ecore_String_Group
+ */
+EAPI const char *
+ecore_string_instance(const char *string)
+{
+ Ecore_String *str;
+
+ CHECK_PARAM_POINTER_RETURN("string", string, NULL);
+
+ /*
+ * Check for a previous instance of the string, if not found, create
+ * it.
+ */
+ str = ecore_hash_get(ecore_strings, string);
+ if (!str)
+ {
+ int length;
+
+ /*
+ * Allocate and initialize a new string reference.
+ */
+ length = strlen(string) + 1;
+
+ str =
+ (Ecore_String *)malloc(sizeof(Ecore_String) + length * sizeof(char));
+
+ str->string = (char *)(str + 1);
+ str->references = 0;
+
+ memcpy(str->string, string, length);
+
+ ecore_hash_set(ecore_strings, str->string, str);
+ }
+
+ str->references++;
+
+ return str->string;
+}
+
+/**
+ * Notes that the given string has lost an instance.
+ *
+ * It will free the string if no other instances are left.
+ *
+ * @param string The given string.
+ * @ingroup Ecore_String_Group
+ */
+EAPI void
+ecore_string_release(const char *string)
+{
+ Ecore_String *str;
+
+ CHECK_PARAM_POINTER("string", string);
+
+ str = ecore_hash_get(ecore_strings, (char *)string);
+ if (!str)
+ return;
+
+ str->references--;
+ if (str->references < 1)
+ {
+ ecore_hash_remove(ecore_strings, (char *)string);
+ FREE(str);
+ }
+}
+
+EAPI void
+ecore_string_hash_dump_graph(void)
+{
+ ecore_hash_dump_graph(ecore_strings);
+}
+
+EAPI void
+ecore_string_hash_dump_stats(void)
+{
+ ecore_hash_dump_stats(ecore_strings);
+}
+
+/**
+ * Shutdown the ecore string internal structures
+ */
+EAPI void
+ecore_string_shutdown()
+{
+ --ecore_string_init_count;
+ if (!ecore_string_init_count)
+ {
+ ecore_hash_destroy(ecore_strings);
+ ecore_strings = NULL;
+ }
+}
+
+static void
+ecore_string_free_cb(void *data)
+{
+ Ecore_String *str;
+
+ str = data;
+ FREE(str);
+}
diff --git a/src/tests/eina/eina_bench.c b/src/tests/eina/eina_bench.c
new file mode 100644
index 000000000..03aaaf941
--- /dev/null
+++ b/src/tests/eina/eina_bench.c
@@ -0,0 +1,104 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include "eina_bench.h"
+#include "Eina.h"
+
+typedef struct _Eina_Benchmark_Case Eina_Benchmark_Case;
+struct _Eina_Benchmark_Case
+{
+ const char *bench_case;
+ void (*build)(Eina_Benchmark *bench);
+};
+
+static const Eina_Benchmark_Case etc[] = {
+ { "Hash", eina_bench_hash },
+ /* { "Array vs List vs Inlist", eina_bench_array }, */
+ /* { "Stringshare", eina_bench_stringshare }, */
+ /* { "Convert", eina_bench_convert }, */
+ /* { "Sort", eina_bench_sort }, */
+ /* { "Mempool", eina_bench_mempool }, */
+ /* { "Rectangle_Pool", eina_bench_rectangle_pool }, */
+ // { "Render Loop", eina_bench_quadtree },
+ { NULL, NULL }
+};
+
+/* FIXME this is a copy from eina_test_mempool
+ * we should remove the duplication
+ */
+static Eina_Array *_modules;
+static void _mempool_init(void)
+{
+ eina_init();
+ /* force modules to be loaded in case they are not installed */
+ _modules = eina_module_list_get(NULL,
+ PACKAGE_BUILD_DIR "/src/modules",
+ EINA_TRUE,
+ NULL,
+ NULL);
+ eina_module_list_load(_modules);
+}
+
+static void _mempool_shutdown(void)
+{
+ eina_module_list_free(_modules);
+ /* TODO delete the list */
+ eina_shutdown();
+}
+
+int
+main(int argc, char **argv)
+{
+ Eina_Benchmark *test;
+ unsigned int i;
+
+ if (argc != 2)
+ return -1;
+
+ _mempool_init();
+
+ eina_init();
+
+ for (i = 0; etc[i].bench_case; ++i)
+ {
+ test = eina_benchmark_new(etc[i].bench_case, argv[1]);
+ if (!test)
+ continue;
+
+ etc[i].build(test);
+
+ eina_benchmark_run(test);
+
+ eina_benchmark_free(test);
+ }
+
+ eina_bench_e17();
+
+ eina_shutdown();
+
+ _mempool_shutdown();
+ return 0;
+}
diff --git a/src/tests/eina/eina_bench.h b/src/tests/eina/eina_bench.h
new file mode 100644
index 000000000..d575822b5
--- /dev/null
+++ b/src/tests/eina/eina_bench.h
@@ -0,0 +1,36 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EINA_BENCH_H_
+#define EINA_BENCH_H_
+
+#include "eina_benchmark.h"
+
+void eina_bench_hash(Eina_Benchmark *bench);
+void eina_bench_array(Eina_Benchmark *bench);
+void eina_bench_stringshare(Eina_Benchmark *bench);
+void eina_bench_convert(Eina_Benchmark *bench);
+void eina_bench_sort(Eina_Benchmark *bench);
+void eina_bench_mempool(Eina_Benchmark *bench);
+void eina_bench_rectangle_pool(Eina_Benchmark *bench);
+void eina_bench_quadtree(Eina_Benchmark *bench);
+
+/* Specific benchmark. */
+void eina_bench_e17(void);
+
+#endif
diff --git a/src/tests/eina/eina_bench_array.c b/src/tests/eina/eina_bench_array.c
new file mode 100644
index 000000000..425eddd94
--- /dev/null
+++ b/src/tests/eina/eina_bench_array.c
@@ -0,0 +1,699 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#ifdef EINA_BENCH_HAVE_GLIB
+# include <glib.h>
+#endif
+
+#include "Evas_Data.h"
+#include "Ecore_Data.h"
+
+#include "eina_bench.h"
+#include "eina_array.h"
+#include "eina_list.h"
+#include "eina_inlist.h"
+#include "eina_main.h"
+
+typedef struct _Eina_Bench_Object Eina_Bench_Object;
+struct _Eina_Bench_Object
+{
+ EINA_INLIST;
+
+ void *somewhere;
+ int data;
+ Eina_Bool keep;
+};
+
+static Eina_Bool keep(void *data, __UNUSED__ void *gdata)
+{
+ Eina_Bench_Object *bo = data;
+
+ if (bo->keep == EINA_TRUE)
+ return EINA_TRUE;
+
+ free(bo);
+ return EINA_FALSE;
+}
+
+static void
+eina_bench_array_4evas_render_inline(int request)
+{
+ Eina_Array *array;
+ Eina_Bench_Object *ebo;
+ Eina_Array_Iterator it;
+ unsigned int i;
+ unsigned int j;
+
+ srand(time(NULL));
+
+ eina_init();
+
+ array = eina_array_new(64);
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < (unsigned int)request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ eina_array_push(array, ebo);
+ }
+
+ if (i == 500)
+ {
+ EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
+ free(ebo);
+
+ eina_array_clean(array);
+ }
+ else if (i % 30 == 0)
+ eina_array_remove(array, keep, NULL);
+
+ EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+ }
+
+ EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
+ free(ebo);
+
+ eina_array_free(array);
+
+ eina_shutdown();
+}
+
+static Eina_Bool
+eina_iterator_ebo_free(__UNUSED__ const Eina_Array *array,
+ Eina_Bench_Object *ebo, __UNUSED__ void *fdata)
+{
+ free(ebo);
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+eina_iterator_ebo_rand(__UNUSED__ const void *container,
+ Eina_Bench_Object *ebo, __UNUSED__ void *fdata)
+{
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+ return EINA_TRUE;
+}
+
+static void
+eina_bench_array_4evas_render_iterator(int request)
+{
+ Eina_Array *array;
+ Eina_Bench_Object *ebo;
+ Eina_Iterator *it;
+ unsigned int i;
+ unsigned int j;
+
+ srand(time(NULL));
+
+ eina_init();
+
+ array = eina_array_new(64);
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < (unsigned int)request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ eina_array_push(array, ebo);
+ }
+
+ if (i == 500)
+ {
+ it = eina_array_iterator_new(array);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_free), NULL);
+ eina_iterator_free(it);
+
+ eina_array_clean(array);
+ }
+ else if (i % 30 == 0)
+ eina_array_remove(array, keep, NULL);
+
+ it = eina_array_iterator_new(array);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_rand), NULL);
+ eina_iterator_free(it);
+ }
+
+ it = eina_array_iterator_new(array);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_free), NULL);
+ eina_iterator_free(it);
+
+ eina_array_free(array);
+
+ eina_shutdown();
+}
+
+static void
+eina_bench_list_4evas_render(int request)
+{
+ Eina_List *list = NULL;
+ Eina_List *tmp;
+ Eina_Bench_Object *ebo;
+ int i;
+ int j;
+
+ eina_init();
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ list = eina_list_prepend(list, ebo);
+ }
+
+ if (i == 500)
+ while (list)
+ {
+ free(eina_list_data_get(list));
+ list = eina_list_remove_list(list, list);
+ }
+ else if (i % 30 == 0)
+ {
+ tmp = list;
+ while (tmp)
+ {
+ Eina_List *reminder = tmp;
+
+ ebo = eina_list_data_get(reminder);
+ tmp = eina_list_next(tmp);
+
+ if (ebo->keep == EINA_FALSE)
+ {
+ list = eina_list_remove_list(list, reminder);
+ free(ebo);
+ }
+ }
+ }
+
+ for (tmp = list; tmp; tmp = eina_list_next(tmp))
+ {
+ ebo = eina_list_data_get(tmp);
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+ }
+ }
+
+ while (list)
+ {
+ free(eina_list_data_get(list));
+ list = eina_list_remove_list(list, list);
+ }
+
+ eina_shutdown();
+}
+
+static void
+eina_bench_list_4evas_render_iterator(int request)
+{
+ Eina_List *list = NULL;
+ Eina_List *tmp;
+ Eina_Bench_Object *ebo;
+ Eina_Iterator *it;
+ int i;
+ int j;
+
+ eina_init();
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ list = eina_list_prepend(list, ebo);
+ }
+
+ if (i == 500)
+ while (list)
+ {
+ free(eina_list_data_get(list));
+ list = eina_list_remove_list(list, list);
+ }
+ else if (i % 30 == 0)
+ {
+ tmp = list;
+ while (tmp)
+ {
+ Eina_List *reminder = tmp;
+
+ ebo = eina_list_data_get(reminder);
+ tmp = eina_list_next(tmp);
+
+ if (ebo->keep == EINA_FALSE)
+ {
+ list = eina_list_remove_list(list, reminder);
+ free(ebo);
+ }
+ }
+ }
+
+ it = eina_list_iterator_new(list);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_rand), NULL);
+ eina_iterator_free(it);
+ }
+
+ while (list)
+ {
+ free(eina_list_data_get(list));
+ list = eina_list_remove_list(list, list);
+ }
+
+ eina_shutdown();
+}
+
+static void
+eina_bench_inlist_4evas_render(int request)
+{
+ Eina_Inlist *head = NULL;
+ Eina_Inlist *tmp;
+ Eina_Bench_Object *ebo;
+ int i;
+ int j;
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ head = eina_inlist_prepend(head, EINA_INLIST_GET(ebo));
+ }
+
+ if (i == 500)
+ while (head)
+ {
+ tmp = head;
+ head = head->next;
+ free(tmp);
+ }
+ else if (i % 30 == 0)
+ {
+ tmp = head;
+ while(tmp)
+ {
+ ebo = (Eina_Bench_Object *)tmp;
+
+ tmp = tmp->next;
+ if (ebo->keep == EINA_FALSE)
+ {
+ head = eina_inlist_remove(head, EINA_INLIST_GET(ebo));
+ free(ebo);
+ }
+ }
+ }
+
+ EINA_INLIST_FOREACH(head, ebo)
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+ }
+
+ while (head)
+ {
+ tmp = head;
+ head = head->next;
+ free(tmp);
+ }
+}
+
+static void
+eina_bench_inlist_4evas_render_iterator(int request)
+{
+ Eina_Inlist *head = NULL;
+ Eina_Inlist *tmp;
+ Eina_Bench_Object *ebo;
+ Eina_Iterator *it;
+ int i;
+ int j;
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ head = eina_inlist_prepend(head, EINA_INLIST_GET(ebo));
+ }
+
+ if (i == 500)
+ while (head)
+ {
+ tmp = head;
+ head = head->next;
+ free(tmp);
+ }
+ else if (i % 30 == 0)
+ {
+ tmp = head;
+ while(tmp)
+ {
+ ebo = (Eina_Bench_Object *)tmp;
+
+ tmp = tmp->next;
+ if (ebo->keep == EINA_FALSE)
+ {
+ head = eina_inlist_remove(head, EINA_INLIST_GET(ebo));
+ free(ebo);
+ }
+ }
+ }
+
+ it = eina_inlist_iterator_new(head);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_rand), NULL);
+ eina_iterator_free(it);
+ }
+
+ while (head)
+ {
+ tmp = head;
+ head = head->next;
+ free(tmp);
+ }
+}
+
+#ifdef EINA_BENCH_HAVE_GLIB
+static void
+eina_bench_glist_4evas_render(int request)
+{
+ GList *list = NULL;
+ GList *tmp;
+ Eina_Bench_Object *ebo;
+ int i;
+ int j;
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ list = g_list_prepend(list, ebo);
+ }
+
+ if (i == 500)
+ while (list)
+ {
+ free(list->data);
+ list = g_list_delete_link(list, list);
+ }
+ else if (i % 30 == 0)
+ {
+ tmp = list;
+ while (tmp)
+ {
+ GList *reminder = tmp;
+
+ ebo = reminder->data;
+ tmp = g_list_next(tmp);
+
+ if (ebo->keep == EINA_FALSE)
+ {
+ list = g_list_delete_link(list, reminder);
+ free(ebo);
+ }
+ }
+ }
+
+ for (tmp = list; tmp; tmp = g_list_next(tmp))
+ {
+ ebo = tmp->data;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+ }
+ }
+
+ while (list)
+ {
+ free(list->data);
+ list = g_list_delete_link(list, list);
+ }
+}
+
+static void
+eina_bench_gptrarray_4evas_render(int request)
+{
+ GPtrArray *array = NULL;
+ Eina_Bench_Object *ebo;
+ unsigned int j;
+ int i;
+
+ array = g_ptr_array_new();
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < (unsigned int)request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ g_ptr_array_add(array, ebo);
+ }
+
+ if (i == 500)
+ {
+ for (j = 0; j < array->len; ++j)
+ free(g_ptr_array_index(array, j));
+ g_ptr_array_remove_range(array, 0, array->len);
+ }
+ else if (i % 30 == 0)
+ for (j = 0; j < array->len; )
+ {
+ ebo = g_ptr_array_index(array, j);
+
+ if (ebo->keep == EINA_FALSE)
+ free(g_ptr_array_remove_index_fast(array, j));
+ else
+ j++;
+ }
+
+ for (j = 0; j < array->len; ++j)
+ {
+ ebo = g_ptr_array_index(array, j);
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+ }
+ }
+
+ for (j = 0; j < array->len; ++j)
+ free(g_ptr_array_index(array, j));
+ g_ptr_array_free(array, TRUE);
+}
+#endif
+
+static void
+eina_bench_evas_list_4evas_render(int request)
+{
+ Evas_List *list = NULL;
+ Evas_List *tmp;
+ Eina_Bench_Object *ebo;
+ int i;
+ int j;
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ list = evas_list_prepend(list, ebo);
+ }
+
+ if (i == 500)
+ while (list)
+ {
+ free(evas_list_data(list));
+ list = evas_list_remove_list(list, list);
+ }
+ else if (i % 30 == 0)
+ {
+ tmp = list;
+ while (tmp)
+ {
+ Evas_List *reminder = tmp;
+
+ ebo = evas_list_data(reminder);
+ tmp = evas_list_next(tmp);
+
+ if (ebo->keep == EINA_FALSE)
+ {
+ list = evas_list_remove_list(list, reminder);
+ free(ebo);
+ }
+ }
+ }
+
+ for (tmp = list; tmp; tmp = evas_list_next(tmp))
+ {
+ ebo = evas_list_data(tmp);
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+ }
+ }
+
+ while (list)
+ {
+ free(evas_list_data(list));
+ list = evas_list_remove_list(list, list);
+ }
+}
+
+static void
+_eina_ecore_for_each_remove(void *value, void *user_data)
+{
+ Eina_Bench_Object *ebo = value;
+ Ecore_List *list = user_data;
+
+ if (ebo->keep == EINA_FALSE)
+ ecore_list_remove_destroy(list);
+}
+
+static void
+_eina_ecore_for_each_rand(void *value, __UNUSED__ void *user_data)
+{
+ Eina_Bench_Object *ebo = value;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
+}
+
+static void
+eina_bench_ecore_list_4evas_render(int request)
+{
+ Ecore_List *list = NULL;
+ Eina_Bench_Object *ebo;
+ int i;
+ int j;
+
+ list = ecore_list_new();
+ ecore_list_free_cb_set(list, free);
+
+ for (i = 0; i < 1000; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ ebo = malloc(sizeof (Eina_Bench_Object));
+ if (!ebo)
+ continue;
+
+ ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+ ecore_list_prepend(list, ebo);
+ }
+
+ if (i == 500)
+ ecore_list_clear(list);
+ else if (i % 30 == 0)
+ ecore_list_for_each(list, _eina_ecore_for_each_remove, list);
+
+ ecore_list_for_each(list, _eina_ecore_for_each_rand, list);
+ }
+
+ ecore_list_destroy(list);
+}
+
+void eina_bench_array(Eina_Benchmark *bench)
+{
+ eina_benchmark_register(bench, "array-inline",
+ EINA_BENCHMARK(
+ eina_bench_array_4evas_render_inline), 200,
+ 4000, 100);
+ eina_benchmark_register(bench, "array-iterator",
+ EINA_BENCHMARK(
+ eina_bench_array_4evas_render_iterator), 200,
+ 4000, 100);
+ eina_benchmark_register(bench, "list",
+ EINA_BENCHMARK(
+ eina_bench_list_4evas_render), 200,
+ 4000, 100);
+ eina_benchmark_register(bench, "list-iterator",
+ EINA_BENCHMARK(
+ eina_bench_list_4evas_render_iterator), 200,
+ 4000, 100);
+ eina_benchmark_register(bench, "inlist",
+ EINA_BENCHMARK(
+ eina_bench_inlist_4evas_render), 200,
+ 4000, 100);
+ eina_benchmark_register(bench, "inlist-iterator",
+ EINA_BENCHMARK(
+ eina_bench_inlist_4evas_render_iterator), 200,
+ 4000, 100);
+#ifdef EINA_BENCH_HAVE_GLIB
+ eina_benchmark_register(bench, "glist",
+ EINA_BENCHMARK(
+ eina_bench_glist_4evas_render), 200,
+ 4000, 100);
+ eina_benchmark_register(bench, "gptrarray",
+ EINA_BENCHMARK(
+ eina_bench_gptrarray_4evas_render), 200,
+ 4000, 100);
+#endif
+ eina_benchmark_register(bench, "evas",
+ EINA_BENCHMARK(
+ eina_bench_evas_list_4evas_render), 200,
+ 4000, 100);
+ eina_benchmark_register(bench, "ecore",
+ EINA_BENCHMARK(
+ eina_bench_ecore_list_4evas_render), 200,
+ 500, 100);
+}
+
diff --git a/src/tests/eina/eina_bench_convert.c b/src/tests/eina/eina_bench_convert.c
new file mode 100644
index 000000000..aafe9ea3b
--- /dev/null
+++ b/src/tests/eina/eina_bench_convert.c
@@ -0,0 +1,183 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+
+#ifdef EINA_BENCH_HAVE_GLIB
+# include <glib.h>
+#endif
+
+#include "eina_bench.h"
+#include "eina_convert.h"
+
+static void
+eina_bench_convert_itoa_10(int request)
+{
+ char tmp[128];
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ eina_convert_itoa(rand(), tmp);
+ }
+}
+
+static void
+eina_bench_convert_itoa_16(int request)
+{
+ char tmp[128];
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ eina_convert_xtoa(rand(), tmp);
+ }
+}
+
+static void
+eina_bench_convert_snprintf_10(int request)
+{
+ char tmp[128];
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ snprintf(tmp, 128, "%i", rand());
+ }
+}
+
+static void
+eina_bench_convert_snprintf_x(int request)
+{
+ char tmp[128];
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ snprintf(tmp, 128, "%x", rand());
+ }
+}
+
+static void
+eina_bench_convert_snprintf_a(int request)
+{
+ char tmp[128];
+ double r;
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ r = 10000 * (rand() / ((double)RAND_MAX + 1));
+ snprintf(tmp, 128, "%a", r);
+ sscanf(tmp, "%la", &r);
+ }
+}
+
+static void
+eina_bench_convert_dtoa(int request)
+{
+ char tmp[128];
+ long long m;
+ long e;
+ double r;
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ r = 10000 * (rand() / ((double)RAND_MAX + 1));
+ eina_convert_dtoa(r, tmp);
+ eina_convert_atod(tmp, 128, &m, &e);
+ r = ldexp((double)m, e);
+ }
+}
+
+#ifdef EINA_BENCH_HAVE_GLIB
+static void
+eina_bench_convert_gstrtod(int request)
+{
+ char tmp[128];
+ double r;
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ r = 10000 * (rand() / ((double)RAND_MAX + 1));
+ g_ascii_dtostr(tmp, 128, r);
+ r = g_ascii_strtod(tmp, NULL);
+ }
+}
+#endif
+
+void eina_bench_convert(Eina_Benchmark *bench)
+{
+ eina_benchmark_register(bench, "itoa 10",
+ EINA_BENCHMARK(
+ eina_bench_convert_itoa_10), 1000, 200000,
+ 500);
+ eina_benchmark_register(bench, "itoa 16",
+ EINA_BENCHMARK(
+ eina_bench_convert_itoa_16), 1000, 200000,
+ 500);
+ eina_benchmark_register(bench, "snprintf 10",
+ EINA_BENCHMARK(
+ eina_bench_convert_snprintf_10), 1000, 200000,
+ 500);
+ eina_benchmark_register(bench, "snprintf 16",
+ EINA_BENCHMARK(
+ eina_bench_convert_snprintf_x), 1000, 200000,
+ 500);
+ eina_benchmark_register(bench, "snprintf a",
+ EINA_BENCHMARK(
+ eina_bench_convert_snprintf_a), 1000, 200000,
+ 500);
+ eina_benchmark_register(bench, "dtoa",
+ EINA_BENCHMARK(
+ eina_bench_convert_dtoa), 1000, 200000,
+ 500);
+#ifdef EINA_BENCH_HAVE_GLIB
+ eina_benchmark_register(bench, "gstrtod",
+ EINA_BENCHMARK(
+ eina_bench_convert_gstrtod), 1000, 200000,
+ 500);
+#endif
+}
+
+
+
+
diff --git a/src/tests/eina/eina_bench_hash.c b/src/tests/eina/eina_bench_hash.c
new file mode 100644
index 000000000..0429097c7
--- /dev/null
+++ b/src/tests/eina/eina_bench_hash.c
@@ -0,0 +1,547 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef EINA_BENCH_HAVE_GLIB
+# include <glib.h>
+#endif
+
+#include "Evas_Data.h"
+#include "Ecore_Data.h"
+
+#include "eina_hash.h"
+#include "eina_array.h"
+#include "eina_bench.h"
+#include "eina_rbtree.h"
+#include "eina_convert.h"
+
+#ifdef CITYHASH_BENCH
+// Hash function for a byte array.
+uint64_t CityHash64(const char *buf, size_t len);
+
+static unsigned int
+_eina_string_key_length(const char *key)
+{
+ if (!key)
+ return 0;
+
+ return (int)strlen(key) + 1;
+}
+
+static int
+_eina_string_key_cmp(const char *key1, __UNUSED__ int key1_length,
+ const char *key2, __UNUSED__ int key2_length)
+{
+ return strcmp(key1, key2);
+}
+#endif
+
+
+typedef struct _Eina_Bench_Rbtree Eina_Bench_Rbtree;
+struct _Eina_Bench_Rbtree
+{
+ Eina_Rbtree node;
+ char key[10];
+ int value;
+};
+
+static Eina_Rbtree_Direction
+_eina_bench_rbtree_cmp(const Eina_Bench_Rbtree *left,
+ const Eina_Bench_Rbtree *right,
+ __UNUSED__ void *data)
+{
+ if (!left)
+ return EINA_RBTREE_RIGHT;
+
+ if (!right)
+ return EINA_RBTREE_LEFT;
+
+ return strcmp(left->key,
+ right->key) < 0 ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
+}
+
+static inline int
+_eina_bench_rbtree_key(const Eina_Bench_Rbtree *node,
+ const char *key,
+ int length,
+ __UNUSED__ void *data)
+{
+ return strncmp(node->key, key, length);
+}
+
+static void
+_eina_bench_rbtree_free(Eina_Rbtree *node, __UNUSED__ void *data)
+{
+ free(node);
+}
+
+static void
+eina_bench_lookup_rbtree(int request)
+{
+ Eina_Rbtree *root = NULL;
+ int i;
+ int j;
+
+ for (i = 0; i < request; ++i)
+ {
+ Eina_Bench_Rbtree *tmp;
+
+ tmp = malloc(sizeof (Eina_Bench_Rbtree));
+ if (!tmp)
+ continue;
+
+ tmp->value = i;
+ eina_convert_itoa(i, tmp->key);
+
+ root = eina_rbtree_inline_insert(root,
+ &tmp->node,
+ EINA_RBTREE_CMP_NODE_CB(
+ _eina_bench_rbtree_cmp),
+ NULL);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < request; ++i)
+ {
+ Eina_Rbtree *tmp;
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+
+ tmp = eina_rbtree_inline_lookup(root,
+ tmp_key,
+ 10,
+ EINA_RBTREE_CMP_KEY_CB(
+ _eina_bench_rbtree_key),
+ NULL);
+ /* Suppress warnings as we really don't want to do anything. */
+ (void) tmp;
+ }
+
+ eina_rbtree_delete(root, EINA_RBTREE_FREE_CB(_eina_bench_rbtree_free), NULL);
+}
+
+static void
+eina_bench_lookup_murmur(int request)
+{
+ Eina_Hash *hash = NULL;
+ int *tmp_val;
+ unsigned int i;
+ unsigned int j;
+
+ hash = eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
+ EINA_KEY_CMP(_eina_string_key_cmp),
+ EINA_KEY_HASH(eina_hash_murmur3),
+ free,
+ 8);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ tmp_val = malloc(sizeof (int));
+
+ if (!tmp_val)
+ continue;
+
+ eina_convert_itoa(i, tmp_key);
+ *tmp_val = i;
+
+ eina_hash_add(hash, tmp_key, tmp_val);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+ tmp_val = eina_hash_find(hash, tmp_key);
+ }
+
+ eina_hash_free(hash);
+}
+
+#ifdef CITYHASH_BENCH
+static void
+eina_bench_lookup_cityhash(int request)
+{
+ Eina_Hash *hash = NULL;
+ int *tmp_val;
+ unsigned int i;
+ unsigned int j;
+
+ hash = eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
+ EINA_KEY_CMP(_eina_string_key_cmp),
+ EINA_KEY_HASH(CityHash64),
+ free,
+ 8);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ tmp_val = malloc(sizeof (int));
+
+ if (!tmp_val)
+ continue;
+
+ eina_convert_itoa(i, tmp_key);
+ *tmp_val = i;
+
+ eina_hash_add(hash, tmp_key, tmp_val);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+ tmp_val = eina_hash_find(hash, tmp_key);
+ }
+
+ eina_hash_free(hash);
+}
+#endif
+
+static void
+eina_bench_lookup_superfast(int request)
+{
+ Eina_Hash *hash = NULL;
+ int *tmp_val;
+ unsigned int i;
+ unsigned int j;
+
+ hash = eina_hash_string_superfast_new(free);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ tmp_val = malloc(sizeof (int));
+
+ if (!tmp_val)
+ continue;
+
+ eina_convert_itoa(i, tmp_key);
+ *tmp_val = i;
+
+ eina_hash_add(hash, tmp_key, tmp_val);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+ tmp_val = eina_hash_find(hash, tmp_key);
+ }
+
+ eina_hash_free(hash);
+}
+
+static void
+eina_bench_lookup_djb2(int request)
+{
+ Eina_Hash *hash = NULL;
+ int *tmp_val;
+ unsigned int i;
+ unsigned int j;
+
+ hash = eina_hash_string_djb2_new(free);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ tmp_val = malloc(sizeof (int));
+
+ if (!tmp_val)
+ continue;
+
+ eina_convert_itoa(i, tmp_key);
+ *tmp_val = i;
+
+ eina_hash_add(hash, tmp_key, tmp_val);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+
+ tmp_val = eina_hash_find(hash, tmp_key);
+ }
+
+ eina_hash_free(hash);
+}
+
+typedef struct _Eina_Bench_DJB2 Eina_Bench_DJB2;
+struct _Eina_Bench_DJB2
+{
+ char *key;
+ int value;
+};
+
+static void
+eina_bench_lookup_djb2_inline(int request)
+{
+ Eina_Hash *hash = NULL;
+ Eina_Bench_DJB2 *elm;
+ unsigned int i;
+ unsigned int j;
+
+ hash = eina_hash_string_djb2_new(free);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ int length;
+
+ elm = malloc(sizeof (Eina_Bench_DJB2) + 10);
+ if (!elm)
+ continue;
+
+ elm->key = (char *)(elm + 1);
+
+ length = eina_convert_itoa(i, elm->key) + 1;
+ elm->value = i;
+
+ eina_hash_direct_add_by_hash(hash, elm->key, length,
+ eina_hash_djb2(elm->key, length), elm);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+ int length = 6;
+
+ length = eina_convert_itoa(rand() % request, tmp_key) + 1;
+
+ elm =
+ eina_hash_find_by_hash(hash, tmp_key, length,
+ eina_hash_djb2(tmp_key, length));
+ }
+
+ eina_hash_free(hash);
+}
+
+#ifdef EINA_BENCH_HAVE_GLIB
+typedef struct _Eina_Bench_Glib Eina_Bench_Glib;
+struct _Eina_Bench_Glib
+{
+ char *key;
+ int value;
+};
+
+static void
+eina_bench_lookup_ghash(int request)
+{
+ Eina_Bench_Glib *elm;
+ GHashTable *hash;
+ unsigned int i;
+ unsigned int j;
+
+ hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ elm = malloc(sizeof (Eina_Bench_Glib) + 10);
+ if (!elm)
+ continue;
+
+ elm->key = (char *)(elm + 1);
+
+ eina_convert_itoa(i, elm->key);
+ elm->value = i;
+
+ g_hash_table_insert(hash, elm->key, elm);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+
+ elm = g_hash_table_lookup(hash, tmp_key);
+ }
+
+ g_hash_table_destroy(hash);
+}
+#endif
+
+static void
+eina_bench_lookup_evas(int request)
+{
+ Evas_Hash *hash = NULL;
+ Eina_Array *array = NULL;
+ int *tmp_val;
+ Eina_Array_Iterator it;
+ unsigned int i;
+ unsigned int j;
+
+ array = eina_array_new(10000);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ tmp_val = malloc(sizeof (int));
+
+ if (!tmp_val)
+ continue;
+
+ eina_convert_itoa(i, tmp_key);
+ *tmp_val = i;
+
+ hash = evas_hash_add(hash, tmp_key, tmp_val);
+
+ eina_array_push(array, tmp_val);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+
+ tmp_val = evas_hash_find(hash, tmp_key);
+ }
+
+ evas_hash_free(hash);
+
+ EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
+ free(tmp_val);
+
+ eina_array_free(array);
+}
+
+typedef struct _Eina_Bench_Ecore Eina_Bench_Ecore;
+struct _Eina_Bench_Ecore
+{
+ char *key;
+ int value;
+};
+
+static void
+eina_bench_lookup_ecore(int request)
+{
+ Ecore_Hash *hash = NULL;
+ Eina_Bench_Ecore *elm;
+ unsigned int i;
+ unsigned int j;
+
+ hash = ecore_hash_new(ecore_str_hash, ecore_str_compare);
+
+ ecore_hash_free_key_cb_set(hash, NULL);
+ ecore_hash_free_value_cb_set(hash, free);
+
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ elm = malloc(sizeof (Eina_Bench_Ecore) + 10);
+ if (!elm)
+ continue;
+
+ elm->key = (char *)(elm + 1);
+ eina_convert_itoa(i, elm->key);
+ elm->value = i;
+
+ ecore_hash_set(hash, elm->key, elm);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < (unsigned int)request; ++i)
+ {
+ char tmp_key[10];
+
+ eina_convert_itoa(rand() % request, tmp_key);
+
+ elm = ecore_hash_get(hash, tmp_key);
+ }
+
+ ecore_hash_destroy(hash);
+}
+
+void eina_bench_hash(Eina_Benchmark *bench)
+{
+ eina_benchmark_register(bench, "superfast-lookup",
+ EINA_BENCHMARK(
+ eina_bench_lookup_superfast), 10, 10000, 10);
+ eina_benchmark_register(bench, "djb2-lookup",
+ EINA_BENCHMARK(
+ eina_bench_lookup_djb2), 10, 10000, 10);
+ eina_benchmark_register(bench, "djb2-lookup-inline",
+ EINA_BENCHMARK(
+ eina_bench_lookup_djb2_inline), 10, 10000, 10);
+ eina_benchmark_register(bench, "murmur",
+ EINA_BENCHMARK(
+ eina_bench_lookup_murmur), 10, 10000, 10);
+#ifdef CITYHASH_BENCH
+ eina_benchmark_register(bench, "cityhash",
+ EINA_BENCHMARK(
+ eina_bench_lookup_cityhash), 10, 10000, 10);
+#endif
+ eina_benchmark_register(bench, "rbtree",
+ EINA_BENCHMARK(
+ eina_bench_lookup_rbtree), 10, 10000, 10);
+#ifdef EINA_BENCH_HAVE_GLIB
+ eina_benchmark_register(bench, "ghash-lookup",
+ EINA_BENCHMARK(
+ eina_bench_lookup_ghash), 10, 10000, 10);
+#endif
+ eina_benchmark_register(bench, "evas-lookup",
+ EINA_BENCHMARK(
+ eina_bench_lookup_evas), 10, 10000, 10);
+ eina_benchmark_register(bench, "ecore-lookup",
+ EINA_BENCHMARK(
+ eina_bench_lookup_ecore), 10, 10000, 10);
+
+}
diff --git a/src/tests/eina/eina_bench_mempool.c b/src/tests/eina/eina_bench_mempool.c
new file mode 100644
index 000000000..d7e2c62ad
--- /dev/null
+++ b/src/tests/eina/eina_bench_mempool.c
@@ -0,0 +1,188 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef EINA_BENCH_HAVE_GLIB
+# include <glib.h>
+#endif
+
+#include "eina_bench.h"
+#include "Eina.h"
+
+static void
+_eina_mempool_bench(Eina_Mempool *mp, int request)
+{
+ Eina_Array *array;
+ int i;
+ int j;
+
+ eina_init();
+ array = eina_array_new(32);
+
+ for (i = 0; i < 100; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ eina_array_push(array, eina_mempool_malloc(mp, sizeof (int)));
+ }
+
+ for (j = 0; j < request; ++j)
+ {
+ eina_mempool_free(mp, eina_array_pop(array));
+ }
+ }
+
+ eina_array_free(array);
+ eina_shutdown();
+}
+
+#ifdef EINA_BUILD_CHAINED_POOL
+static void
+eina_mempool_chained_mempool(int request)
+{
+ Eina_Mempool *mp;
+
+ mp = eina_mempool_add("chained_mempool", "test", NULL, sizeof (int), 256);
+ _eina_mempool_bench(mp, request);
+ eina_mempool_del(mp);
+}
+#endif
+
+#ifdef EINA_BUILD_PASS_THROUGH
+static void
+eina_mempool_pass_through(int request)
+{
+ Eina_Mempool *mp;
+
+ mp = eina_mempool_add("pass_through", "test", NULL, sizeof (int), 8, 0);
+ _eina_mempool_bench(mp, request);
+ eina_mempool_del(mp);
+}
+#endif
+
+#ifdef EINA_BUILD_FIXED_BITMAP
+static void
+eina_mempool_fixed_bitmap(int request)
+{
+ Eina_Mempool *mp;
+
+ mp = eina_mempool_add("fixed_bitmap", "test", NULL, sizeof (int));
+ _eina_mempool_bench(mp, request);
+ eina_mempool_del(mp);
+}
+#endif
+
+#ifdef EINA_BUILD_EMEMOA_FIXED
+static void
+eina_mempool_ememoa_fixed(int request)
+{
+ Eina_Mempool *mp;
+
+ mp = eina_mempool_add("ememoa_fixed", "test", NULL, sizeof (int), 8, 0);
+ _eina_mempool_bench(mp, request);
+ eina_mempool_del(mp);
+}
+#endif
+
+#ifdef EINA_BUILD_EMEMOA_UNKNOWN
+static void
+eina_mempool_ememoa_unknown(int request)
+{
+ Eina_Mempool *mp;
+
+ mp = eina_mempool_add("ememoa_unknown",
+ "test",
+ NULL,
+ 0,
+ 2,
+ sizeof (int),
+ 8,
+ sizeof (int) * 2,
+ 8);
+ _eina_mempool_bench(mp, request);
+ eina_mempool_del(mp);
+}
+#endif
+
+#ifdef EINA_BENCH_HAVE_GLIB
+static void
+eina_mempool_glib(int request)
+{
+ Eina_Array *array;
+ int i;
+ int j;
+
+ eina_init();
+ array = eina_array_new(32);
+
+ for (i = 0; i < 100; ++i)
+ {
+ for (j = 0; j < request; ++j)
+ {
+ eina_array_push(array, g_slice_alloc(sizeof (int)));
+ }
+
+ for (j = 0; j < request; ++j)
+ {
+ g_slice_free1(sizeof (int), eina_array_pop(array));
+ }
+ }
+
+ eina_array_free(array);
+ eina_shutdown();
+
+}
+#endif
+
+void
+eina_bench_mempool(Eina_Benchmark *bench)
+{
+#ifdef EINA_BUILD_CHAINED_POOL
+ eina_benchmark_register(bench, "chained mempool",
+ EINA_BENCHMARK(
+ eina_mempool_chained_mempool), 10, 10000, 10);
+#endif
+#ifdef EINA_BUILD_PASS_THROUGH
+ eina_benchmark_register(bench, "pass through",
+ EINA_BENCHMARK(
+ eina_mempool_pass_through), 10, 10000, 10);
+#endif
+#ifdef EINA_BUILD_FIXED_BITMAP
+ eina_benchmark_register(bench, "fixed bitmap",
+ EINA_BENCHMARK(
+ eina_mempool_fixed_bitmap), 10, 10000, 10);
+#endif
+#ifdef EINA_BUILD_EMEMOA_FIXED
+ eina_benchmark_register(bench, "ememoa fixed",
+ EINA_BENCHMARK(
+ eina_mempool_ememoa_fixed), 10, 10000, 10);
+#endif
+#ifdef EINA_BUILD_EMEMOA_UNKNOWN
+ eina_benchmark_register(bench, "ememoa unknown",
+ EINA_BENCHMARK(
+ eina_mempool_ememoa_unknown), 10, 10000, 10);
+#endif
+#ifdef EINA_BENCH_HAVE_GLIB
+ eina_benchmark_register(bench, "gslice",
+ EINA_BENCHMARK(
+ eina_mempool_glib), 10, 10000, 10);
+#endif
+}
diff --git a/src/tests/eina/eina_bench_quad.c b/src/tests/eina/eina_bench_quad.c
new file mode 100644
index 000000000..8401fd476
--- /dev/null
+++ b/src/tests/eina/eina_bench_quad.c
@@ -0,0 +1,320 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2010 Cedric BAIL
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define WIDTH 720
+#define HEIGHT 576
+
+#include <stdlib.h>
+
+#include "eina_main.h"
+#include "eina_mempool.h"
+#include "eina_rectangle.h"
+#include "eina_quadtree.h"
+#include "eina_list.h"
+#include "eina_bench.h"
+
+static void
+eina_bench_render_loop(int request)
+{
+ Eina_List *objects = NULL;
+ Eina_Rectangle *r;
+ int i;
+ int j;
+
+ eina_init();
+
+ for (i = 0; i < request; ++i)
+ objects = eina_list_append(objects,
+ eina_rectangle_new((rand() * WIDTH) / RAND_MAX,
+ (rand() *
+ HEIGHT) / RAND_MAX,
+ (rand() * WIDTH /
+ 2) / RAND_MAX,
+ (rand() * HEIGHT /
+ 2) / RAND_MAX));
+
+ for (j = 0; j < 100; ++j)
+ {
+ Eina_Rectangle *collide;
+ Eina_List *collided = NULL;
+ Eina_List *changed = NULL;
+ Eina_List *l;
+
+ /* Delete 25% of all objects */
+ i = request * 25 / 100;
+ for (; i > 0; --i)
+ {
+ eina_rectangle_free(eina_list_data_get(objects));
+ objects = eina_list_remove_list(objects, objects);
+ }
+
+ /* Add them back */
+ i = request * 25 / 100;
+ for (; i > 0; --i)
+ {
+ r = eina_rectangle_new((rand() * WIDTH) / RAND_MAX,
+ (rand() * HEIGHT) / RAND_MAX,
+ (rand() * WIDTH / 3) / RAND_MAX,
+ (rand() * HEIGHT / 3) / RAND_MAX);
+ objects = eina_list_prepend(objects, r);
+ changed = eina_list_append(changed, r);
+ }
+
+ /* Do one collide search */
+ collide = eina_rectangle_new((rand() * WIDTH) / RAND_MAX,
+ (rand() * HEIGHT) / RAND_MAX,
+ (rand() * WIDTH / 4) / RAND_MAX,
+ (rand() * HEIGHT / 4) / RAND_MAX);
+ EINA_LIST_FOREACH(objects, l, r)
+ if (eina_rectangles_intersect(r, collide))
+ collided = eina_list_append(collided, r);
+
+ collided = eina_list_free(collided);
+ eina_rectangle_free(collide);
+
+ /* Modify 50% of all objects */
+ i = request * 50 / 100;
+ for (; i > 0; --i)
+ {
+ r = eina_list_data_get(eina_list_last(objects));
+ objects = eina_list_remove_list(objects, eina_list_last(objects));
+
+ r->x = (rand() * WIDTH) / RAND_MAX;
+ r->y = (rand() * HEIGHT) / RAND_MAX;
+ r->w = (rand() * WIDTH / 3) / RAND_MAX;
+ r->h = (rand() * HEIGHT / 3) / RAND_MAX;
+
+ objects = eina_list_prepend(objects, r);
+ changed = eina_list_append(changed, r);
+ }
+
+ /* Emulating the render loop by colliding all modified
+ object with all intersecting object */
+ EINA_LIST_FREE(changed, r)
+ {
+ EINA_LIST_FOREACH(objects, l, collide)
+ if (r != collide && eina_rectangles_intersect(collide, r))
+ collided = eina_list_append(collided, collide);
+
+ collided = eina_list_append(collided, r);
+ }
+
+ /* Ok, we compute it, now it's done */
+ collided = eina_list_free(collided);
+ }
+
+ EINA_LIST_FREE(objects, r)
+ eina_rectangle_free(r);
+
+ eina_shutdown();
+}
+
+typedef struct _Eina_Bench_Quad Eina_Bench_Quad;
+struct _Eina_Bench_Quad
+{
+ Eina_Rectangle r;
+ Eina_QuadTree_Item *item;
+};
+
+static Eina_Quad_Direction
+_eina_bench_quadtree_vertical(const void *object, size_t middle)
+{
+ const Eina_Bench_Quad *b = object;
+ size_t y;
+
+ y = b->r.y < 0 ? 0 : (size_t)b->r.y;
+
+ if (y + b->r.h < middle)
+ return EINA_QUAD_LEFT;
+
+ if (y > middle)
+ return EINA_QUAD_RIGHT;
+
+ return EINA_QUAD_BOTH;
+}
+
+static Eina_Quad_Direction
+_eina_bench_quadtree_horizontal(const void *object, size_t middle)
+{
+ const Eina_Bench_Quad *b = object;
+ size_t x;
+
+ x = b->r.x < 0 ? 0 : (size_t)b->r.x;
+
+ if (x + b->r.w < middle)
+ return EINA_QUAD_LEFT;
+
+ if (x > middle)
+ return EINA_QUAD_RIGHT;
+
+ return EINA_QUAD_BOTH;
+}
+
+static void
+eina_bench_quadtree_render_loop(int request)
+{
+ Eina_List *objects = NULL;
+ Eina_Inlist *possibility;
+ Eina_Bench_Quad *b;
+ Eina_QuadTree *q;
+ Eina_Mempool *mp;
+ int i;
+ int j;
+
+ eina_init();
+
+ mp = eina_mempool_add("chained_mempool", "bench-quad", NULL,
+ sizeof (Eina_Bench_Quad), 320);
+
+ q = eina_quadtree_new(WIDTH, HEIGHT,
+ _eina_bench_quadtree_vertical,
+ _eina_bench_quadtree_horizontal);
+
+ /* Create requested object */
+ for (i = 0; i < request; ++i)
+ {
+ b = eina_mempool_malloc(mp, sizeof (Eina_Bench_Quad));
+ EINA_RECTANGLE_SET(&b->r,
+ (rand() * WIDTH) / RAND_MAX,
+ (rand() * HEIGHT) / RAND_MAX,
+ (rand() * WIDTH / 2) / RAND_MAX,
+ (rand() * HEIGHT / 2) / RAND_MAX);
+ b->item = eina_quadtree_add(q, b);
+
+ objects = eina_list_append(objects, b);
+ }
+
+ for (j = 0; j < 100; ++j)
+ {
+ Eina_Bench_Quad *collide;
+ Eina_List *changed = NULL;
+ Eina_List *collided = NULL;
+
+ /* Delete 25% of all objects */
+ i = request * 25 / 100;
+ for (; i > 0; --i)
+ {
+ b = eina_list_data_get(objects);
+ eina_quadtree_del(b->item);
+ eina_mempool_free(mp, b);
+
+ objects = eina_list_remove_list(objects, objects);
+ }
+
+ /* Add them back */
+ i = request * 25 / 100;
+ for (; i > 0; --i)
+ {
+ b = eina_mempool_malloc(mp, sizeof (Eina_Bench_Quad));
+ EINA_RECTANGLE_SET(&b->r,
+ (rand() * WIDTH) / RAND_MAX,
+ (rand() * HEIGHT) / RAND_MAX,
+ (rand() * WIDTH / 3) / RAND_MAX,
+ (rand() * HEIGHT / 3) / RAND_MAX);
+ b->item = eina_quadtree_add(q, b);
+
+ objects = eina_list_prepend(objects, b);
+ changed = eina_list_append(changed, b);
+ }
+
+ /* Do one collide search */
+ collide = eina_mempool_malloc(mp, sizeof (Eina_Bench_Quad));
+ EINA_RECTANGLE_SET(&collide->r,
+ (rand() * WIDTH) / RAND_MAX,
+ (rand() * HEIGHT) / RAND_MAX,
+ (rand() * WIDTH / 4) / RAND_MAX,
+ (rand() * HEIGHT / 4) / RAND_MAX);
+ possibility = eina_quadtree_collide(q,
+ collide->r.x, collide->r.y,
+ collide->r.w, collide->r.h);
+ while (possibility)
+ {
+ b = eina_quadtree_object(possibility);
+ possibility = possibility->next;
+
+ if (eina_rectangles_intersect(&b->r, &collide->r))
+ collided = eina_list_append(collided, b);
+ }
+
+ collided = eina_list_free(collided);
+ eina_mempool_free(mp, collide);
+
+ /* Modify 50% of all objects */
+ i = request * 50 / 100;
+ for (; i > 0; --i)
+ {
+ b = eina_list_data_get(eina_list_last(objects));
+ objects = eina_list_remove_list(objects, eina_list_last(objects));
+
+ b->r.x = (rand() * WIDTH) / RAND_MAX;
+ b->r.y = (rand() * HEIGHT) / RAND_MAX;
+ b->r.w = (rand() * WIDTH / 3) / RAND_MAX;
+ b->r.h = (rand() * HEIGHT / 3) / RAND_MAX;
+
+ eina_quadtree_change(b->item);
+
+ objects = eina_list_prepend(objects, b);
+ changed = eina_list_append(changed, b);
+ }
+
+ /* Emulating the render loop by colliding all modified
+ object with all intersecting object */
+ EINA_LIST_FREE(changed, b)
+ {
+ possibility = eina_quadtree_collide(q,
+ b->r.x, b->r.y, b->r.w, b->r.h);
+ while (possibility)
+ {
+ collide = eina_quadtree_object(possibility);
+ possibility = possibility->next;
+
+ if (collide != b &&
+ eina_rectangles_intersect(&b->r, &collide->r))
+ collided = eina_list_append(collided, collide);
+ }
+
+ collided = eina_list_append(collided, b);
+ }
+
+ /* Ok, we compute it, now it's done */
+ collided = eina_list_free(collided);
+ }
+
+ EINA_LIST_FREE(objects, b)
+ {
+ eina_quadtree_del(b->item);
+ eina_mempool_free(mp, b);
+ }
+
+ eina_mempool_del(mp);
+
+ eina_quadtree_free(q);
+
+ eina_shutdown();
+}
+
+void
+eina_bench_quadtree(Eina_Benchmark *bench)
+{
+ eina_benchmark_register(bench, "collide-all",
+ EINA_BENCHMARK(eina_bench_render_loop),
+ 100, 1500, 50);
+ eina_benchmark_register(bench, "collide-quad-tree",
+ EINA_BENCHMARK(eina_bench_quadtree_render_loop),
+ 100, 1500, 50);
+}
diff --git a/src/tests/eina/eina_bench_rectangle_pool.c b/src/tests/eina/eina_bench_rectangle_pool.c
new file mode 100644
index 000000000..96d4b1bf0
--- /dev/null
+++ b/src/tests/eina/eina_bench_rectangle_pool.c
@@ -0,0 +1,76 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "eina_bench.h"
+#include "Eina.h"
+
+static void
+eina_bench_eina_rectangle_pool(int request)
+{
+ Eina_Rectangle_Pool *pool;
+ Eina_Rectangle *rect;
+ Eina_List *list = NULL;
+ int i;
+
+ eina_init();
+ eina_init();
+
+ pool = eina_rectangle_pool_new(2048, 2048);
+ if (!pool)
+ return;
+
+ for (i = 0; i < request; ++i)
+ {
+ rect = NULL;
+
+ while (!rect)
+ {
+ rect = eina_rectangle_pool_request(pool, i & 0xFF, 256 - (i & 0xFF));
+ if (!rect)
+ {
+ rect = eina_list_data_get(list);
+ list = eina_list_remove_list(list, list);
+ if (rect)
+ eina_rectangle_pool_release(rect);
+ }
+ else
+ list = eina_list_append(list, rect);
+
+ if (!(i & 0xFF))
+ break;
+ }
+ }
+
+ eina_rectangle_pool_free(pool);
+ eina_list_free(list);
+
+ eina_shutdown();
+}
+
+void eina_bench_rectangle_pool(Eina_Benchmark *bench)
+{
+ eina_benchmark_register(bench, "eina",
+ EINA_BENCHMARK(
+ eina_bench_eina_rectangle_pool), 10, 4000, 100);
+}
+
+
diff --git a/src/tests/eina/eina_bench_sort.c b/src/tests/eina/eina_bench_sort.c
new file mode 100644
index 000000000..c3c9d9ff9
--- /dev/null
+++ b/src/tests/eina/eina_bench_sort.c
@@ -0,0 +1,222 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef EINA_BENCH_HAVE_GLIB
+# include <glib.h>
+#endif
+
+#include "Evas_Data.h"
+#include "Ecore_Data.h"
+
+#include "eina_bench.h"
+#include "eina_convert.h"
+#include "eina_list.h"
+#include "eina_main.h"
+
+static int
+_eina_cmp_str(const char *a, const char *b)
+{
+ return strcmp(a, b);
+}
+
+static void
+eina_bench_sort_eina(int request)
+{
+ Eina_List *list = NULL;
+ int i;
+
+ eina_init();
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ char buffer[10];
+
+ eina_convert_itoa(rand() % request, buffer);
+
+ list = eina_list_prepend(list, strdup(buffer));
+ }
+
+ list = eina_list_sort(list, -1, EINA_COMPARE_CB(_eina_cmp_str));
+
+ while (list)
+ {
+ free(eina_list_data_get(list));
+ list = eina_list_remove_list(list, list);
+ }
+
+ eina_shutdown();
+}
+
+static void
+eina_bench_sort_evas(int request)
+{
+ Evas_List *list = NULL;
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ char buffer[10];
+
+ eina_convert_itoa(rand() % request, buffer);
+
+ list = evas_list_prepend(list, strdup(buffer));
+ }
+
+ list = evas_list_sort(list, -1, (void *)_eina_cmp_str);
+
+ while (list)
+ {
+ free(evas_list_data(list));
+ list = evas_list_remove_list(list, list);
+ }
+}
+
+#ifdef EINA_BENCH_HAVE_GLIB
+static void
+eina_bench_sort_glist(int request)
+{
+ GList *list = NULL;
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < request; ++i)
+ {
+ char buffer[10];
+
+ eina_convert_itoa(rand() % request, buffer);
+
+ list = g_list_prepend(list, strdup(buffer));
+ }
+
+ list = g_list_sort(list, (void *)_eina_cmp_str);
+
+ while (list)
+ {
+ free(list->data);
+ list = g_list_delete_link(list, list);
+ }
+}
+#endif
+
+static void
+eina_bench_sort_ecore_default(int request)
+{
+ Ecore_List *list = NULL;
+ int i;
+
+ list = ecore_list_new();
+ ecore_list_free_cb_set(list, free);
+
+ for (i = 0; i < request; ++i)
+ {
+ char buffer[10];
+
+ eina_convert_itoa(rand() % request, buffer);
+
+ ecore_list_prepend(list, strdup(buffer));
+ }
+
+ ecore_list_sort(list, ECORE_COMPARE_CB(_eina_cmp_str), 0);
+
+ ecore_list_destroy(list);
+}
+
+static void
+eina_bench_sort_ecore_merge(int request)
+{
+ Ecore_List *list = NULL;
+ int i;
+
+ list = ecore_list_new();
+ ecore_list_free_cb_set(list, free);
+
+ for (i = 0; i < request; ++i)
+ {
+ char buffer[10];
+
+ eina_convert_itoa(rand() % request, buffer);
+
+ ecore_list_prepend(list, strdup(buffer));
+ }
+
+ ecore_list_mergesort(list, ECORE_COMPARE_CB(_eina_cmp_str), 0);
+
+ ecore_list_destroy(list);
+}
+
+static void
+eina_bench_sort_ecore_heap(int request)
+{
+ Ecore_List *list = NULL;
+ int i;
+
+ list = ecore_list_new();
+ ecore_list_free_cb_set(list, free);
+
+ for (i = 0; i < request; ++i)
+ {
+ char buffer[10];
+
+ eina_convert_itoa(rand() % request, buffer);
+
+ ecore_list_prepend(list, strdup(buffer));
+ }
+
+ ecore_list_heapsort(list, ECORE_COMPARE_CB(_eina_cmp_str), 0);
+
+ ecore_list_destroy(list);
+}
+
+void eina_bench_sort(Eina_Benchmark *bench)
+{
+ eina_benchmark_register(bench, "eina",
+ EINA_BENCHMARK(
+ eina_bench_sort_eina), 10, 10000, 100);
+#ifdef EINA_BENCH_HAVE_GLIB
+ eina_benchmark_register(bench, "glist",
+ EINA_BENCHMARK(
+ eina_bench_sort_glist), 10, 10000, 100);
+#endif
+ eina_benchmark_register(bench, "ecore",
+ EINA_BENCHMARK(
+ eina_bench_sort_ecore_default), 10, 10000, 100);
+ eina_benchmark_register(bench, "ecore-merge",
+ EINA_BENCHMARK(
+ eina_bench_sort_ecore_merge), 10, 10000, 100);
+ eina_benchmark_register(bench, "ecore-heap",
+ EINA_BENCHMARK(
+ eina_bench_sort_ecore_heap), 10, 10000, 100);
+ eina_benchmark_register(bench, "evas",
+ EINA_BENCHMARK(
+ eina_bench_sort_evas), 10, 10000, 100);
+}
+
+
+
diff --git a/src/tests/eina/eina_bench_stringshare.c b/src/tests/eina/eina_bench_stringshare.c
new file mode 100644
index 000000000..22d18fa48
--- /dev/null
+++ b/src/tests/eina/eina_bench_stringshare.c
@@ -0,0 +1,185 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#ifdef EINA_BENCH_HAVE_GLIB
+# include <glib.h>
+#endif
+
+#include "Evas_Data.h"
+#include "Ecore_Data.h"
+
+#include "eina_stringshare.h"
+#include "eina_bench.h"
+#include "eina_convert.h"
+#include "eina_main.h"
+
+static void
+eina_bench_stringshare_job(int request)
+{
+ const char *tmp;
+ unsigned int j;
+ int i;
+
+ eina_init();
+
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(i, build + 7);
+ tmp = eina_stringshare_add(build);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(rand() % request, build + 7);
+ tmp = eina_stringshare_add(build);
+ }
+
+ /* Suppress warnings as we really don't want to do anything. */
+ (void) tmp;
+ eina_shutdown();
+}
+
+#ifdef EINA_BENCH_HAVE_GLIB
+static void
+eina_bench_stringchunk_job(int request)
+{
+ GStringChunk *chunk;
+ unsigned int j;
+ int i;
+
+ chunk = g_string_chunk_new(4096);
+
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(i, build + 7);
+ g_string_chunk_insert_const(chunk, build);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(rand() % request, build + 7);
+ g_string_chunk_insert_const(chunk, build);
+ }
+
+ g_string_chunk_free(chunk);
+}
+#endif
+
+static void
+eina_bench_evas_job(int request)
+{
+ const char *tmp;
+ unsigned int j;
+ int i;
+
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(i, build + 7);
+ tmp = evas_stringshare_add(build);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(rand() % request, build + 7);
+ tmp = evas_stringshare_add(build);
+ }
+
+ /* Suppress warnings as we really don't want to do anything. */
+ (void) tmp;
+}
+
+static void
+eina_bench_ecore_job(int request)
+{
+ const char *tmp;
+ unsigned int j;
+ int i;
+
+ ecore_string_init();
+
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(i, build + 7);
+ tmp = ecore_string_instance(build);
+ }
+
+ srand(time(NULL));
+
+ for (j = 0; j < 200; ++j)
+ for (i = 0; i < request; ++i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(rand() % request, build + 7);
+ tmp = ecore_string_instance(build);
+ }
+
+ /* Suppress warnings as we really don't want to do anything. */
+ (void) tmp;
+
+ ecore_string_shutdown();
+}
+
+void eina_bench_stringshare(Eina_Benchmark *bench)
+{
+ eina_benchmark_register(bench, "stringshare",
+ EINA_BENCHMARK(
+ eina_bench_stringshare_job), 100, 20100, 500);
+#ifdef EINA_BENCH_HAVE_GLIB
+ eina_benchmark_register(bench, "stringchunk (glib)",
+ EINA_BENCHMARK(
+ eina_bench_stringchunk_job), 100, 20100, 500);
+#endif
+ eina_benchmark_register(bench, "stringshare (evas)",
+ EINA_BENCHMARK(
+ eina_bench_evas_job), 100, 20100, 500);
+ eina_benchmark_register(bench, "stringshare (ecore)",
+ EINA_BENCHMARK(
+ eina_bench_ecore_job), 100, 20100, 500);
+}
diff --git a/src/tests/eina/eina_bench_stringshare_e17.c b/src/tests/eina/eina_bench_stringshare_e17.c
new file mode 100644
index 000000000..6ab0a807e
--- /dev/null
+++ b/src/tests/eina/eina_bench_stringshare_e17.c
@@ -0,0 +1,118 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#ifdef EINA_BENCH_HAVE_GLIB
+# include <glib.h>
+#endif
+
+#include "Evas_Data.h"
+#include "Ecore_Data.h"
+
+#include "Eina.h"
+
+#if EINA_ENABLE_BENCH_E17
+
+typedef struct _Eina_Stringshare_Test Eina_Stringshare_Test;
+struct _Eina_Stringshare_Test
+{
+ const char *name;
+
+ int (*init)(void);
+ const char *(*add)(const char *str);
+ void (*del)(const char *str);
+ int (*shutdown)(void);
+};
+
+static const char *strings[30000];
+static Eina_Stringshare_Test eina_str = {
+ "eina",
+ eina_init,
+ eina_stringshare_add,
+ eina_stringshare_del,
+ eina_shutdown
+};
+
+static Eina_Stringshare_Test evas_str = {
+ "evas",
+/* evas_stringshare_init, */
+ evas_stringshare_add,
+ evas_stringshare_del
+/* evas_stringshare_shutdown */
+};
+
+static Eina_Stringshare_Test ecore_str = {
+ "ecore",
+ ecore_string_init,
+ ecore_string_instance,
+ ecore_string_release,
+ ecore_string_shutdown
+};
+
+static Eina_Stringshare_Test *str[] = {
+ &eina_str,
+ &evas_str,
+ &ecore_str,
+ NULL
+};
+
+static void
+eina_bench_e17_stringshare(Eina_Stringshare_Test *str)
+{
+ Eina_Counter *cnt;
+
+ cnt = eina_counter_new(str->name);
+
+ eina_counter_start(cnt);
+
+ str->init();
+
+#include "strlog"
+
+ str->shutdown();
+
+ eina_counter_stop(cnt, 1);
+
+ fprintf(stderr, "For `%s`:\n", str->name);
+ eina_counter_dump(cnt);
+
+ eina_counter_free(cnt);
+}
+#endif
+
+void
+eina_bench_e17(void)
+{
+#if EINA_ENABLE_BENCH_E17
+ int i;
+
+ eina_init();
+
+ for (i = 0; str[i]; ++i)
+ eina_bench_e17_stringshare(str[i]);
+
+ eina_shutdown();
+#endif
+}
diff --git a/src/tests/eina/eina_suite.c b/src/tests/eina/eina_suite.c
new file mode 100644
index 000000000..d69cd4708
--- /dev/null
+++ b/src/tests/eina/eina_suite.c
@@ -0,0 +1,183 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "eina_suite.h"
+#include "Eina.h"
+#include <stdio.h>
+#include <string.h>
+
+typedef struct _Eina_Test_Case Eina_Test_Case;
+struct _Eina_Test_Case
+{
+ const char *test_case;
+ void (*build)(TCase *tc);
+};
+
+static const Eina_Test_Case etc[] = {
+ { "FixedPoint", eina_test_fp },
+ { "Inarray", eina_test_inarray },
+ { "Array", eina_test_array },
+ { "Binary Share", eina_test_binshare },
+ { "String Share", eina_test_stringshare },
+ { "UString Share", eina_test_ustringshare },
+ { "Log", eina_test_log },
+ { "Error", eina_test_error },
+ { "Magic", eina_test_magic },
+ { "Inlist", eina_test_inlist },
+ { "Lazy alloc", eina_test_lalloc },
+ { "Main", eina_test_main },
+ { "Counter", eina_test_counter },
+ { "Hash", eina_test_hash },
+ { "List", eina_test_list },
+ { "CList", eina_test_clist },
+ { "Iterator", eina_test_iterator },
+ { "Accessor", eina_test_accessor },
+ { "Module", eina_test_module },
+ { "Convert", eina_test_convert },
+ { "Rbtree", eina_test_rbtree },
+ { "File", eina_test_file },
+ { "Benchmark", eina_test_benchmark },
+ { "Mempool", eina_test_mempool },
+ { "Rectangle", eina_test_rectangle },
+ { "Matrix Sparse", eina_test_matrixsparse },
+ { "Eina Tiler", eina_test_tiler },
+ { "Eina Strbuf", eina_test_strbuf },
+ { "Eina Binbuf", eina_test_binbuf },
+ { "String", eina_test_str },
+ { "Unicode String", eina_test_ustr },
+ { "QuadTree", eina_test_quadtree },
+ { "Sched", eina_test_sched },
+ { "Simple Xml Parser", eina_test_simple_xml_parser},
+ { "Value", eina_test_value },
+ // Disabling Eina_Model test
+ // { "Model", eina_test_model },
+ { NULL, NULL }
+};
+
+static void
+_list_tests(void)
+{
+ const Eina_Test_Case *itr = etc;
+ fputs("Available Test Cases:\n", stderr);
+ for (; itr->test_case; itr++)
+ fprintf(stderr, "\t%s\n", itr->test_case);
+}
+
+static Eina_Bool
+_use_test(int argc, const char **argv, const char *test_case)
+{
+ if (argc < 1)
+ return 1;
+
+ for (; argc > 0; argc--, argv++)
+ if (strcmp(test_case, *argv) == 0)
+ return 1;
+
+ return 0;
+}
+
+Suite *
+eina_build_suite(int argc, const char **argv)
+{
+ TCase *tc;
+ Suite *s;
+ int i;
+
+ s = suite_create("Eina");
+
+ for (i = 0; etc[i].test_case; ++i)
+ {
+ if (!_use_test(argc, argv, etc[i].test_case))
+ continue;
+
+ tc = tcase_create(etc[i].test_case);
+
+ etc[i].build(tc);
+
+ suite_add_tcase(s, tc);
+ tcase_set_timeout(tc, 0);
+ }
+
+ return s;
+}
+
+/* FIXME this is a copy from eina_test_mempool
+ * we should remove the duplication
+ */
+static Eina_Array *_modules;
+static void _mempool_init(void)
+{
+ eina_init();
+ /* force modules to be loaded in case they are not installed */
+ _modules = eina_module_list_get(NULL,
+ PACKAGE_BUILD_DIR "/src/modules",
+ EINA_TRUE,
+ NULL,
+ NULL);
+ eina_module_list_load(_modules);
+}
+
+static void _mempool_shutdown(void)
+{
+ eina_module_list_free(_modules);
+ if (_modules)
+ eina_array_free(_modules);
+ /* TODO delete the list */
+ eina_shutdown();
+}
+
+int
+main(int argc, char **argv)
+{
+ Suite *s;
+ SRunner *sr;
+ int i, failed_count;
+
+ for (i = 1; i < argc; i++)
+ if ((strcmp(argv[i], "-h") == 0) ||
+ (strcmp(argv[i], "--help") == 0))
+ {
+ fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n",
+ argv[0]);
+ _list_tests();
+ return 0;
+ }
+ else if ((strcmp(argv[i], "-l") == 0) ||
+ (strcmp(argv[i], "--list") == 0))
+ {
+ _list_tests();
+ return 0;
+ }
+
+ s = eina_build_suite(argc - 1, (const char **)argv + 1);
+ sr = srunner_create(s);
+
+ _mempool_init();
+
+ srunner_run_all(sr, CK_ENV);
+ failed_count = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ _mempool_shutdown();
+
+ return (failed_count == 0) ? 0 : 255;
+}
diff --git a/src/tests/eina/eina_suite.h b/src/tests/eina/eina_suite.h
new file mode 100644
index 000000000..d39929812
--- /dev/null
+++ b/src/tests/eina/eina_suite.h
@@ -0,0 +1,61 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EINA_SUITE_H_
+#define EINA_SUITE_H_
+
+#include <check.h>
+
+void eina_test_stringshare(TCase *tc);
+void eina_test_ustringshare(TCase *tc);
+void eina_test_binshare(TCase *tc);
+void eina_test_inarray(TCase *tc);
+void eina_test_array(TCase *tc);
+void eina_test_log(TCase *tc);
+void eina_test_error(TCase *tc);
+void eina_test_magic(TCase *tc);
+void eina_test_inlist(TCase *tc);
+void eina_test_clist(TCase *tc);
+void eina_test_lalloc(TCase *tc);
+void eina_test_main(TCase *tc);
+void eina_test_counter(TCase *tc);
+void eina_test_hash(TCase *tc);
+void eina_test_list(TCase *tc);
+void eina_test_iterator(TCase *tc);
+void eina_test_accessor(TCase *tc);
+void eina_test_module(TCase *tc);
+void eina_test_convert(TCase *tc);
+void eina_test_rbtree(TCase *tc);
+void eina_test_file(TCase *tc);
+void eina_test_benchmark(TCase *tc);
+void eina_test_mempool(TCase *tc);
+void eina_test_rectangle(TCase *tc);
+void eina_test_matrixsparse(TCase *tc);
+void eina_test_tiler(TCase *tc);
+void eina_test_strbuf(TCase *tc);
+void eina_test_binbuf(TCase *tc);
+void eina_test_str(TCase *tc);
+void eina_test_ustr(TCase *tc);
+void eina_test_quadtree(TCase *tc);
+void eina_test_fp(TCase *tc);
+void eina_test_sched(TCase *tc);
+void eina_test_simple_xml_parser(TCase *tc);
+void eina_test_value(TCase *tc);
+void eina_test_model(TCase *tc);
+
+#endif /* EINA_SUITE_H_ */
diff --git a/src/tests/eina/eina_test_accessor.c b/src/tests/eina/eina_test_accessor.c
new file mode 100644
index 000000000..3c85ef037
--- /dev/null
+++ b/src/tests/eina/eina_test_accessor.c
@@ -0,0 +1,243 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static Eina_Bool
+eina_accessor_check(__UNUSED__ const Eina_Array *array,
+ int *data, int *fdata)
+{
+ fail_if(*fdata > *data);
+ *fdata = *data;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_accessor_array_simple)
+{
+ Eina_Accessor *it;
+ Eina_Array *ea;
+ int *tmp;
+ int i;
+
+ eina_init();
+
+ ea = eina_array_new(11);
+ fail_if(!ea);
+
+ for (i = 0; i < 200; ++i)
+ {
+ tmp = malloc(sizeof(int));
+ fail_if(!tmp);
+ *tmp = i;
+
+ eina_array_push(ea, tmp);
+ }
+
+ it = eina_array_accessor_new(ea);
+ fail_if(!it);
+
+ fail_if(eina_accessor_data_get(it, 100, (void **)&tmp) != EINA_TRUE);
+ fail_if(!tmp);
+ fail_if(*tmp != 100);
+
+ i = 50;
+ eina_accessor_over(it, EINA_EACH_CB(eina_accessor_check), 50, 100, &i);
+ fail_if(i != 99);
+
+ fail_if(eina_accessor_container_get(it) != ea);
+
+ eina_accessor_free(it);
+
+ eina_array_free(ea);
+
+ eina_shutdown();
+}
+END_TEST
+
+typedef struct _Eina_Test_Inlist Eina_Test_Inlist;
+struct _Eina_Test_Inlist
+{
+ EINA_INLIST;
+ int i;
+};
+
+static Eina_Test_Inlist *
+_eina_test_inlist_build(int i)
+{
+ Eina_Test_Inlist *tmp;
+
+ tmp = malloc(sizeof(Eina_Test_Inlist));
+ fail_if(!tmp);
+ tmp->i = i;
+
+ return tmp;
+}
+
+static Eina_Bool
+eina_accessor_inlist_data_check(__UNUSED__ const Eina_Inlist *in_list,
+ Eina_Test_Inlist *data,
+ int *fdata)
+{
+ switch (*fdata)
+ {
+ case 0: fail_if(data->i != 3227); break;
+
+ case 1: fail_if(data->i != 1664); break;
+ }
+
+ (*fdata)++;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_accessor_inlist_simple)
+{
+ Eina_Inlist *lst = NULL;
+ Eina_Test_Inlist *tmp;
+ Eina_Test_Inlist *prev;
+ Eina_Accessor *it;
+ int i = 0;
+
+ tmp = _eina_test_inlist_build(42);
+ lst = eina_inlist_append(lst, EINA_INLIST_GET(tmp));
+ fail_if(!lst);
+
+ tmp = _eina_test_inlist_build(1664);
+ lst = eina_inlist_append_relative(lst, EINA_INLIST_GET(tmp), lst);
+ fail_if(!lst);
+ fail_if(((Eina_Test_Inlist *)lst)->i != 42);
+
+ prev = tmp;
+ tmp = _eina_test_inlist_build(3227);
+ lst = eina_inlist_prepend_relative(lst, EINA_INLIST_GET(
+ tmp), EINA_INLIST_GET(prev));
+ fail_if(!lst);
+ fail_if(((Eina_Test_Inlist *)lst)->i != 42);
+
+ tmp = _eina_test_inlist_build(27);
+ lst = eina_inlist_prepend_relative(lst, EINA_INLIST_GET(tmp), NULL);
+
+ tmp = _eina_test_inlist_build(81);
+ lst = eina_inlist_append_relative(lst, EINA_INLIST_GET(tmp), NULL);
+
+ tmp = _eina_test_inlist_build(7);
+ lst = eina_inlist_append(lst, EINA_INLIST_GET(tmp));
+
+ it = eina_inlist_accessor_new(lst);
+ fail_if(!it);
+ fail_if(eina_accessor_container_get(it) != lst);
+
+ eina_accessor_over(it, EINA_EACH_CB(eina_accessor_inlist_data_check), 2, 4, &i);
+
+ fail_if(eina_accessor_data_get(it, 5, (void **)&tmp) != EINA_TRUE);
+ fail_if(eina_accessor_data_get(it, 3, (void **)&tmp) != EINA_TRUE);
+ fail_if(tmp->i != 1664);
+ fail_if(eina_accessor_data_get(it, 3, (void **)&tmp) != EINA_TRUE);
+ fail_if(tmp->i != 1664);
+ fail_if(eina_accessor_data_get(it, 1, (void **)&tmp) != EINA_TRUE);
+ fail_if(tmp->i != 42);
+
+ eina_accessor_free(it);
+
+ fail_if(i != 2);
+}
+END_TEST
+
+static Eina_Bool
+eina_iterator_list_data_check(__UNUSED__ const Eina_List *list,
+ int *data,
+ int *fdata)
+{
+ switch (*fdata)
+ {
+ case 0: fail_if(*data != 9); break;
+
+ case 1: fail_if(*data != 6); break;
+ }
+
+ (*fdata)++;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_accessor_list_simple)
+{
+ Eina_List *list = NULL;
+ Eina_Accessor *it;
+ int data[] = { 6, 9, 42, 1, 7, 1337, 81, 1664 };
+ int *j;
+ int i = 0;
+
+ eina_init();
+
+ list = eina_list_append(list, &data[0]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend(list, &data[1]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[2]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[3]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend(list, &data[4]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[5]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend(list, &data[6]);
+ fail_if(list == NULL);
+
+ it = eina_list_accessor_new(list);
+ fail_if(!it);
+
+ eina_accessor_over(it, EINA_EACH_CB(eina_iterator_list_data_check), 2, 4, &i);
+
+ fail_if(eina_accessor_data_get(it, 5, (void **)&j) != EINA_TRUE);
+ fail_if(*j != 1);
+ fail_if(eina_accessor_data_get(it, 3, (void **)&j) != EINA_TRUE);
+ fail_if(*j != 6);
+ fail_if(eina_accessor_data_get(it, 3, (void **)&j) != EINA_TRUE);
+ fail_if(*j != 6);
+ fail_if(eina_accessor_data_get(it, 1, (void **)&j) != EINA_TRUE);
+ fail_if(*j != 7);
+ fail_if(eina_accessor_data_get(it, 5, (void **)&j) != EINA_TRUE);
+ fail_if(*j != 1);
+
+ eina_accessor_free(it);
+}
+END_TEST
+
+void
+eina_test_accessor(TCase *tc)
+{
+ tcase_add_test(tc, eina_accessor_array_simple);
+ tcase_add_test(tc, eina_accessor_inlist_simple);
+ tcase_add_test(tc, eina_accessor_list_simple);
+}
diff --git a/src/tests/eina/eina_test_array.c b/src/tests/eina/eina_test_array.c
new file mode 100644
index 000000000..192960183
--- /dev/null
+++ b/src/tests/eina/eina_test_array.c
@@ -0,0 +1,191 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(eina_array_simple)
+{
+ Eina_Array *ea;
+ char *tmp;
+ Eina_Array_Iterator it;
+ unsigned int i;
+
+ eina_init();
+
+ ea = eina_array_new(11);
+ fail_if(!ea);
+
+ for (i = 0; i < 201; ++i)
+ {
+ tmp = malloc(sizeof(char) * 10);
+ fail_if(!tmp);
+ eina_convert_itoa(i, tmp);
+
+ eina_array_push(ea, tmp);
+ }
+
+ fail_if(eina_array_data_get(ea, 10) == NULL);
+ fail_if(atoi(eina_array_data_get(ea, 10)) != 10);
+ tmp = eina_array_pop(ea);
+ fail_if(tmp == NULL);
+ fail_if(atoi(tmp) != 200);
+ free(tmp);
+
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
+ {
+ fail_if((unsigned int)atoi(tmp) != i);
+ free(tmp);
+ }
+
+ fail_if(i != 200);
+
+ eina_array_clean(ea);
+ eina_array_flush(ea);
+ eina_array_free(ea);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_array_static)
+{
+ Eina_Array sea;
+ char *tmp;
+ Eina_Array_Iterator it;
+ unsigned int i;
+
+ eina_init();
+
+ eina_array_step_set(&sea, sizeof(sea), 10);
+
+ for (i = 0; i < 200; ++i)
+ {
+ tmp = malloc(sizeof(char) * 10);
+ fail_if(!tmp);
+ eina_convert_itoa(i, tmp);
+
+ eina_array_push(&sea, tmp);
+ }
+
+ fail_if(eina_array_data_get(&sea, 10) == NULL);
+ fail_if(atoi(eina_array_data_get(&sea, 10)) != 10);
+
+ EINA_ARRAY_ITER_NEXT(&sea, i, tmp, it)
+ {
+ fail_if((unsigned int)atoi(tmp) != i);
+ free(tmp);
+ }
+
+ fail_if(i != 200);
+
+ eina_array_clean(&sea);
+ eina_array_flush(&sea);
+
+ eina_shutdown();
+}
+END_TEST
+
+Eina_Bool
+keep_int(void *data, void *gdata)
+{
+ int *tmp = data;
+
+ fail_if(gdata);
+ fail_if(!tmp);
+
+ if (*tmp == 0)
+ return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_array_remove_stuff)
+{
+ Eina_Array *ea;
+ int *tmp;
+ Eina_Array_Iterator it;
+ unsigned int i;
+
+ eina_init();
+
+ ea = eina_array_new(64);
+ fail_if(!ea);
+
+ for (i = 0; i < 1000; ++i)
+ {
+ tmp = malloc(sizeof(int));
+ fail_if(!tmp);
+ *tmp = i;
+
+ eina_array_push(ea, tmp);
+ }
+
+ // Remove the first 10 items
+ for (i = 0; i < 10; ++i)
+ {
+ tmp = eina_array_data_get(ea, i);
+ fail_if(!tmp);
+ *tmp = 0;
+ }
+ fail_if(eina_array_remove(ea, keep_int, NULL) != EINA_TRUE);
+
+ fail_if(eina_array_count(ea) != 990);
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
+ fail_if(*tmp == 0);
+
+ // Remove the last items
+ for (i = 980; i < 990; ++i)
+ {
+ tmp = eina_array_data_get(ea, i);
+ fail_if(!tmp);
+ *tmp = 0;
+ }
+ eina_array_remove(ea, keep_int, NULL);
+
+ // Remove all items
+ fail_if(eina_array_count(ea) != 980);
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
+ {
+ fail_if(*tmp == 0);
+ *tmp = 0;
+ }
+
+ eina_array_remove(ea, keep_int, NULL);
+
+ fail_if(eina_array_count(ea) != 0);
+
+ eina_array_free(ea);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_array(TCase *tc)
+{
+ tcase_add_test(tc, eina_array_simple);
+ tcase_add_test(tc, eina_array_static);
+ tcase_add_test(tc, eina_array_remove_stuff);
+}
diff --git a/src/tests/eina/eina_test_benchmark.c b/src/tests/eina/eina_test_benchmark.c
new file mode 100644
index 000000000..4352c1622
--- /dev/null
+++ b/src/tests/eina/eina_test_benchmark.c
@@ -0,0 +1,76 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include "eina_suite.h"
+#include "eina_benchmark.h"
+
+static int global_test = 0;
+
+static void
+_eina_benchmark_specimens(int request)
+{
+ int i;
+ int a = 0;
+
+ for (i = 0; i < request; ++i)
+ a += i;
+
+ global_test = a;
+}
+
+START_TEST(eina_benchmark_simple)
+{
+ Eina_Benchmark *eb;
+ Eina_Array_Iterator it;
+ Eina_Array *ea;
+ char *tmp;
+ unsigned int i;
+
+ eb = eina_benchmark_new("benchmark", "test");
+ fail_if(!eb);
+
+ eina_benchmark_register(eb, "specimens_check",
+ EINA_BENCHMARK(_eina_benchmark_specimens),
+ 1000, 1100, 100);
+
+ ea = eina_benchmark_run(eb);
+ fail_if(!ea);
+
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
+ {
+ fail_if(!tmp);
+ fail_if(unlink(tmp));
+ }
+
+ fail_if(global_test != 499500);
+
+ eina_benchmark_free(eb);
+}
+END_TEST
+
+void
+eina_test_benchmark(TCase *tc)
+{
+ tcase_add_test(tc, eina_benchmark_simple);
+}
diff --git a/src/tests/eina/eina_test_binbuf.c b/src/tests/eina/eina_test_binbuf.c
new file mode 100644
index 000000000..d62072eba
--- /dev/null
+++ b/src/tests/eina/eina_test_binbuf.c
@@ -0,0 +1,263 @@
+/* EINA - EFL data type library
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(binbuf_simple)
+{
+ Eina_Binbuf *buf;
+ unsigned char *txt;
+ const unsigned char cbuf[] = "Null in the middle \0 and more text afterwards and \0 anotehr null just there and another one \0 here.";
+ size_t size = sizeof(cbuf) - 1; /* We don't care about the real NULL */
+
+
+ eina_init();
+
+ buf = eina_binbuf_new();
+ fail_if(!buf);
+
+ eina_binbuf_append_length(buf, cbuf, size);
+ fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size));
+ fail_if(size != eina_binbuf_length_get(buf));
+
+ eina_binbuf_append_length(buf, cbuf, size);
+ fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size));
+ fail_if(memcmp(eina_binbuf_string_get(buf) + size, cbuf, size));
+ fail_if(2 * size != eina_binbuf_length_get(buf));
+
+ txt = eina_binbuf_string_steal(buf);
+ fail_if(memcmp(txt, cbuf, size));
+ fail_if(memcmp(txt + size, cbuf, size));
+ free(txt);
+ fail_if(eina_binbuf_length_get(buf) != 0);
+
+ eina_binbuf_append_length(buf, cbuf, size);
+ fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size));
+ fail_if(size != eina_binbuf_length_get(buf));
+
+ eina_binbuf_reset(buf);
+ fail_if(eina_binbuf_length_get(buf) != 0);
+
+ eina_binbuf_free(buf);
+
+ eina_shutdown();
+#undef TEXT
+}
+END_TEST
+
+START_TEST(binbuf_remove)
+{
+ Eina_Binbuf *buf;
+ const unsigned char cbuf[] = "12\0 456 78\0 abcthis is some more random junk here!";
+ size_t size = sizeof(cbuf) - 1; /* We don't care about the real NULL */
+
+ eina_init();
+
+ buf = eina_binbuf_new();
+ fail_if(!buf);
+
+ eina_binbuf_append_length(buf, cbuf, size);
+ fail_if(size != eina_binbuf_length_get(buf));
+ eina_binbuf_remove(buf, 0, 4);
+ fail_if(size - 4 != eina_binbuf_length_get(buf));
+ eina_binbuf_remove(buf, 8, 1000);
+ fail_if(8 != eina_binbuf_length_get(buf));
+ eina_binbuf_remove(buf, 7, eina_binbuf_length_get(buf));
+ fail_if(7 != eina_binbuf_length_get(buf));
+ eina_binbuf_remove(buf, 2, 4);
+ fail_if(5 != eina_binbuf_length_get(buf));
+ eina_binbuf_remove(buf, 4, 1);
+ fail_if(5 != eina_binbuf_length_get(buf));
+ eina_binbuf_remove(buf, 0, eina_binbuf_length_get(buf));
+ fail_if(0 != eina_binbuf_length_get(buf));
+
+ eina_binbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(binbuf_manage_simple)
+{
+ Eina_Binbuf *buf;
+ const char *_cbuf = "12\0 456 78\0 abcthis is some more random junk here!";
+ const unsigned char *cbuf = (const unsigned char *) _cbuf;
+ size_t size = sizeof(cbuf) - 1; /* We don't care about the real NULL */
+ unsigned char *alloc_buf = malloc(size);
+ memcpy(alloc_buf, cbuf, size);
+
+ eina_init();
+
+ buf = eina_binbuf_manage_new_length(alloc_buf, size);
+ fail_if(!buf);
+
+ fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size));
+ fail_if(size != eina_binbuf_length_get(buf));
+ eina_binbuf_append_length(buf, cbuf, size);
+ fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size));
+ fail_if(memcmp(eina_binbuf_string_get(buf) + size, cbuf, size));
+ fail_if(2 * size != eina_binbuf_length_get(buf));
+
+ eina_binbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(binbuf_insert)
+{
+#if 0
+ Eina_Binbuf *buf;
+
+ eina_init();
+
+ buf = eina_binbuf_new();
+ fail_if(!buf);
+
+ eina_binbuf_insert(buf, "abc", 10);
+ fail_if(strlen(eina_binbuf_string_get(buf)) != eina_binbuf_length_get(buf));
+ fail_if(strcmp(eina_binbuf_string_get(buf), "abc"));
+
+ eina_binbuf_insert(buf, "123", 0);
+ fail_if(strlen(eina_binbuf_string_get(buf)) != eina_binbuf_length_get(buf));
+ fail_if(strcmp(eina_binbuf_string_get(buf), "123abc"));
+
+ eina_binbuf_insert(buf, "xyz", eina_binbuf_length_get(buf));
+ fail_if(strlen(eina_binbuf_string_get(buf)) != eina_binbuf_length_get(buf));
+ fail_if(strcmp(eina_binbuf_string_get(buf), "123abcxyz"));
+
+ eina_binbuf_insert(buf, "xyz", 1);
+ fail_if(strlen(eina_binbuf_string_get(buf)) != eina_binbuf_length_get(buf));
+ fail_if(strcmp(eina_binbuf_string_get(buf), "1xyz23abcxyz"));
+
+ eina_binbuf_insert_n(buf, "ABCDEF", 2, 1);
+ fail_if(strlen(eina_binbuf_string_get(buf)) != eina_binbuf_length_get(buf));
+ fail_if(strcmp(eina_binbuf_string_get(buf), "1ABxyz23abcxyz"));
+
+ eina_binbuf_insert_n(buf, "EINA", 2, 3);
+ fail_if(strlen(eina_binbuf_string_get(buf)) != eina_binbuf_length_get(buf));
+ fail_if(strcmp(eina_binbuf_string_get(buf), "1ABEIxyz23abcxyz"));
+
+ eina_binbuf_insert_escaped(buf, "678", 3);
+ fail_if(strlen(eina_binbuf_string_get(buf)) != eina_binbuf_length_get(buf));
+ fail_if(strncmp(eina_binbuf_string_get(buf) + 3, "678", 3));
+
+ eina_binbuf_insert_escaped(buf, "089 '\\", 9);
+ fail_if(strlen(eina_binbuf_string_get(
+ buf)) != eina_binbuf_length_get(buf));
+ fail_if(strncmp(eina_binbuf_string_get(buf) + 9,
+ "089\\ \\'\\\\",
+ strlen("089\\ \\'\\\\")));
+ eina_binbuf_reset(buf);
+
+ eina_binbuf_free(buf);
+
+ eina_shutdown();
+#endif
+}
+END_TEST
+
+START_TEST(binbuf_realloc)
+{
+ Eina_Binbuf *buf;
+ unsigned char pattern[1024 * 16];
+ unsigned int i;
+ size_t sz;
+
+ for (i = 0; i < sizeof(pattern) - 1; i++)
+ {
+ if (i % 27 == 26)
+ pattern[i] = '\0';
+ else
+ pattern[i] = 'a' + (i % 27);
+ }
+ pattern[i] = '\0';
+
+ eina_init();
+
+ buf = eina_binbuf_new();
+ fail_if(!buf);
+
+ sz = 0;
+
+ eina_binbuf_append_length(buf, pattern, 1);
+ fail_if(eina_binbuf_length_get(buf) != sz + 1);
+ fail_if(memcmp(eina_binbuf_string_get(buf) + sz, pattern, 1));
+ sz += 1;
+
+ eina_binbuf_append_length(buf, pattern, 32);
+ fail_if(eina_binbuf_length_get(buf) != sz + 32);
+ fail_if(memcmp(eina_binbuf_string_get(buf) + sz, pattern, 32));
+ sz += 32;
+
+ eina_binbuf_append_length(buf, pattern, 64);
+ fail_if(eina_binbuf_length_get(buf) != sz + 64);
+ fail_if(memcmp(eina_binbuf_string_get(buf) + sz, pattern, 64));
+ sz += 64;
+
+ eina_binbuf_append_length(buf, pattern, 128);
+ fail_if(eina_binbuf_length_get(buf) != sz + 128);
+ fail_if(memcmp(eina_binbuf_string_get(buf) + sz, pattern, 128));
+ sz += 128;
+
+ eina_binbuf_append_length(buf, pattern, 4096);
+ fail_if(eina_binbuf_length_get(buf) != sz + 4096);
+ fail_if(memcmp(eina_binbuf_string_get(buf) + sz, pattern, 4096));
+ sz += 4096;
+
+ eina_binbuf_append_length(buf, pattern, sizeof(pattern) - 1);
+ fail_if(eina_binbuf_length_get(buf) != sz + sizeof(pattern) - 1);
+ fail_if(memcmp(eina_binbuf_string_get(buf) + sz, pattern, sizeof(pattern) -
+ 1));
+ sz += sizeof(pattern) - 1;
+
+
+ eina_binbuf_remove(buf, 1024, 1024 + 1234);
+ fail_if(eina_binbuf_length_get(buf) != sz - 1234);
+ sz -= 1234;
+
+ eina_binbuf_remove(buf, 0, 0 + 8192);
+ fail_if(eina_binbuf_length_get(buf) != sz - 8192);
+ sz -= 8192;
+
+ eina_binbuf_remove(buf, 0, 0 + 32);
+ fail_if(eina_binbuf_length_get(buf) != sz - 32);
+ sz -= 32;
+
+
+ eina_binbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_binbuf(TCase *tc)
+{
+ tcase_add_test(tc, binbuf_simple);
+ tcase_add_test(tc, binbuf_remove);
+ tcase_add_test(tc, binbuf_insert);
+ tcase_add_test(tc, binbuf_realloc);
+ tcase_add_test(tc, binbuf_manage_simple);
+}
diff --git a/src/tests/eina/eina_test_binshare.c b/src/tests/eina/eina_test_binshare.c
new file mode 100644
index 000000000..b2e77ae55
--- /dev/null
+++ b/src/tests/eina/eina_test_binshare.c
@@ -0,0 +1,199 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+#define TEST0 "te\0st/0"
+#define TEST0_SIZE 7
+#define TEST1 "te\0st/11"
+#define TEST1_SIZE 8
+
+START_TEST(eina_binshare_simple)
+{
+ const char *t0;
+ const char *t1;
+
+ eina_init();
+
+ t0 = eina_binshare_add_length(TEST0, TEST0_SIZE);
+ t1 = eina_binshare_add_length(TEST1, TEST1_SIZE);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(memcmp(t0, TEST0, TEST0_SIZE) != 0);
+ fail_if(memcmp(t1, TEST1, TEST1_SIZE) != 0);
+
+ t0 = eina_binshare_ref(t0);
+ fail_if(t0 == NULL);
+ fail_if(memcmp(t0, TEST0, TEST0_SIZE) != 0);
+
+ eina_binshare_del(t0);
+ eina_binshare_del(t0);
+ eina_binshare_del(t1);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_binshare_small)
+{
+ char buf[4];
+ int i;
+
+ eina_init();
+
+ for (i = 1; i < 3; i++)
+ {
+ const char *t0, *t1;
+ int j;
+
+ for (j = 0; j < i; j++)
+ {
+ char c;
+ for (c = 'a'; c <= 'z'; c++)
+ buf[j] = c;
+ }
+ buf[i] = '\0';
+ t0 = eina_binshare_add_length(buf, i);
+ t1 = eina_binshare_add_length(buf, i);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(t0 != t1);
+ fail_if(memcmp(t0, buf, i) != 0);
+
+ eina_binshare_del(t0);
+ eina_binshare_del(t1);
+ }
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_binshare_test_share)
+{
+ const char *t0;
+ const char *t1;
+
+ eina_init();
+
+ t0 = eina_binshare_add_length(TEST0, TEST0_SIZE);
+ t1 = eina_binshare_add_length(TEST0, TEST0_SIZE);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(memcmp(t0, TEST0, TEST0_SIZE) != 0);
+ fail_if(memcmp(t1, TEST0, TEST0_SIZE) != 0);
+ fail_if(t0 != t1);
+ fail_if(TEST0_SIZE != eina_binshare_length(t0));
+
+ eina_binshare_del(t0);
+ eina_binshare_del(t1);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_binshare_putstuff)
+{
+ const char *tmp;
+ int i;
+
+ eina_init();
+
+ for (i = 10000; i > 0; --i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(i, build + 7);
+ tmp = eina_binshare_add_length(build, strlen(build));
+ fail_if(tmp != eina_binshare_add_length(build, strlen(build)));
+ fail_if((int)strlen(build) != eina_binshare_length(tmp));
+ }
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_binshare_collision)
+{
+ Eina_Array *ea;
+ char buffer[50];
+ int i;
+
+ srand(time(NULL));
+
+ eina_init();
+
+ ea = eina_array_new(256);
+ fail_if(!ea);
+
+ for (i = 0; i < 10000; ++i)
+ {
+ eina_convert_itoa(rand(), buffer);
+ eina_array_push(ea,
+ (void *)eina_binshare_add_length(buffer, strlen(buffer)));
+ if (rand() > RAND_MAX / 2)
+ {
+ const char *r = eina_binshare_add_length(buffer, strlen(buffer));
+ fail_if(r == NULL);
+ }
+ }
+
+ for (i = 0; i < 10000; ++i)
+ {
+ const char *r;
+
+ eina_convert_itoa(60000 - i, buffer);
+ eina_array_push(ea,
+ (void *)eina_binshare_add_length(buffer, strlen(buffer)));
+ r = eina_binshare_add_length(buffer, strlen(buffer));
+ fail_if(r == NULL);
+ r = eina_binshare_add_length(buffer, strlen(buffer));
+ fail_if(r == NULL);
+ }
+
+ for (i = 0; i < 200; ++i)
+ eina_binshare_del(eina_array_data_get(ea, i));
+
+ for (i = 0; i < 1000; ++i)
+ eina_binshare_del(eina_array_pop(ea));
+
+ eina_shutdown();
+
+ eina_array_free(ea);
+}
+END_TEST
+
+void
+eina_test_binshare(TCase *tc)
+{
+ tcase_add_test(tc, eina_binshare_simple);
+ tcase_add_test(tc, eina_binshare_small);
+ tcase_add_test(tc, eina_binshare_test_share);
+ tcase_add_test(tc, eina_binshare_collision);
+ tcase_add_test(tc, eina_binshare_putstuff);
+}
diff --git a/src/tests/eina/eina_test_clist.c b/src/tests/eina/eina_test_clist.c
new file mode 100644
index 000000000..115afc233
--- /dev/null
+++ b/src/tests/eina/eina_test_clist.c
@@ -0,0 +1,89 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "Eina.h"
+#include "eina_suite.h"
+
+Eina_Clist string_list = EINA_CLIST_INIT(string_list);
+
+struct test_string
+{
+ Eina_Clist entry;
+ const char *string;
+};
+
+static void add_string(const char *foo)
+{
+ struct test_string *t;
+
+ t = malloc(sizeof *t);
+ assert(t != NULL);
+
+ t->string = foo;
+ eina_clist_add_tail(&string_list, &t->entry);
+}
+
+static void print_strings(void)
+{
+ struct test_string *str;
+
+ EINA_CLIST_FOR_EACH_ENTRY(str, &string_list, struct test_string, entry)
+ {
+ printf("%s ", str->string);
+ }
+ printf("\n");
+}
+
+static void free_list(void)
+{
+ struct test_string *str, *tmp;
+
+ EINA_CLIST_FOR_EACH_ENTRY_SAFE(str, tmp, &string_list, struct test_string, entry)
+ {
+ eina_clist_remove(&str->entry);
+ }
+}
+
+START_TEST(eina_clist_basic)
+{
+ unsigned int n = 0;
+
+ add_string("this");
+ n++;
+ add_string("is");
+ n++;
+ add_string("a");
+ n++;
+ add_string("test");
+ n++;
+ add_string("of");
+ n++;
+ add_string("clists");
+ n++;
+ add_string("-");
+ n++;
+ add_string("hello");
+ n++;
+ add_string("world");
+ n++;
+
+ fail_if(eina_clist_count(&string_list) != n);
+
+ print_strings();
+
+ free_list();
+
+ fail_if(eina_clist_count(&string_list) != 0);
+}
+END_TEST
+
+void
+eina_test_clist(TCase *tc)
+{
+ tcase_add_test(tc, eina_clist_basic);
+}
diff --git a/src/tests/eina/eina_test_convert.c b/src/tests/eina/eina_test_convert.c
new file mode 100644
index 000000000..8e7f58c26
--- /dev/null
+++ b/src/tests/eina/eina_test_convert.c
@@ -0,0 +1,165 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(eina_convert_simple)
+{
+ char tmp[128];
+
+ fail_if(eina_convert_itoa(0, tmp) != 1);
+ fail_if(strcmp(tmp, "0") != 0);
+
+ fail_if(eina_convert_itoa(-1, tmp) != 2);
+ fail_if(strcmp(tmp, "-1") != 0);
+
+ fail_if(eina_convert_itoa(100, tmp) != 3);
+ fail_if(strcmp(tmp, "100") != 0);
+
+ fail_if(eina_convert_itoa(-100, tmp) != 4);
+ fail_if(strcmp(tmp, "-100") != 0);
+
+ fail_if(eina_convert_itoa(10000000, tmp) != 8);
+ fail_if(strcmp(tmp, "10000000") != 0);
+
+ fail_if(eina_convert_xtoa(0, tmp) != 1);
+ fail_if(strcmp(tmp, "0") != 0);
+
+ fail_if(eina_convert_xtoa(0xA1, tmp) != 2);
+ fail_if(strcmp(tmp, "a1") != 0);
+
+ fail_if(eina_convert_xtoa(0xFF00EF0E, tmp) != 8);
+ fail_if(strcmp(tmp, "ff00ef0e") != 0);
+}
+END_TEST
+
+#define EET_TEST_DOUBLE0 123.45689
+#define EET_TEST_DOUBLE1 1.0
+#define EET_TEST_DOUBLE2 0.25
+#define EET_TEST_DOUBLE3 0.0001234
+#define EET_TEST_DOUBLE4 123456789.9876543210
+
+static void
+_eina_convert_check(double test, int length)
+{
+ char tmp[128];
+ long long int m = 0;
+ long e = 0;
+ double r;
+
+ fail_if(eina_convert_dtoa(test, tmp) != length);
+ fail_if(eina_convert_atod(tmp, 128, &m, &e) != EINA_TRUE);
+ r = ldexp((double)m, e);
+ fail_if(fabs(r - test) > DBL_MIN);
+}
+
+ START_TEST(eina_convert_double)
+{
+ long long int m = 0;
+ long e = 0;
+
+ eina_init();
+
+ _eina_convert_check(EET_TEST_DOUBLE0, 20);
+ _eina_convert_check(-EET_TEST_DOUBLE0, 21);
+ _eina_convert_check(EET_TEST_DOUBLE1, 6);
+ _eina_convert_check(EET_TEST_DOUBLE2, 6);
+ _eina_convert_check(EET_TEST_DOUBLE3, 21);
+ _eina_convert_check(EET_TEST_DOUBLE4, 21);
+
+ fail_if(eina_convert_atod("ah ah ah", 8, &m, &e) != EINA_FALSE);
+ fail_if(eina_convert_atod("0xjo", 8, &m, &e) != EINA_FALSE);
+ fail_if(eina_convert_atod("0xp", 8, &m, &e) != EINA_FALSE);
+
+ eina_shutdown();
+}
+END_TEST
+
+static void
+_eina_convert_fp_check(double d, Eina_F32p32 fp, int length)
+{
+ char tmp1[128];
+ char tmp2[128];
+ Eina_F32p32 fpc;
+ double fpd;
+ int l1;
+ int l2;
+
+ l1 = eina_convert_dtoa(d, tmp1);
+ l2 = eina_convert_fptoa(fp, tmp2);
+/* fprintf(stderr, "[%s](%i) vs [%s](%i)\n", tmp1, l1, tmp2, l2); */
+ fail_if(l1 != l2);
+ fail_if(length != l1);
+ fail_if(strcmp(tmp1, tmp2) != 0);
+
+ fail_if(!eina_convert_atofp(tmp2, l2, &fpc));
+/* fprintf(stderr, "%016x vs %016x\n", fpc, fp); */
+ fail_if(fpc != fp);
+
+ fail_if(!eina_convert_atofp(tmp1, l1, &fpc));
+ fpd = eina_f32p32_double_to(fpc);
+/* fprintf(stderr, "%0.16f vs %0.16f\n", fpd, d); */
+ fail_if(fabs(fpd - d) > DBL_MIN);
+
+ d = -d;
+ fp = -fp;
+
+ l1 = eina_convert_dtoa(d, tmp1);
+ l2 = eina_convert_fptoa(fp, tmp2);
+ fail_if(l1 != l2);
+ fail_if(length + 1 != l1);
+ fail_if(strcmp(tmp1, tmp2) != 0);
+
+ fail_if(!eina_convert_atofp(tmp2, l2, &fpc));
+/* fprintf(stderr, "%016x vs %016x\n", fpc, fp); */
+ fail_if(fpc != fp);
+
+ fail_if(!eina_convert_atofp(tmp1, l1, &fpc));
+ fpd = eina_f32p32_double_to(fpc);
+/* fprintf(stderr, "%0.16f vs %0.16f\n", fpd, d); */
+ fail_if(fabs(fpd - d) > DBL_MIN);
+}
+
+ START_TEST(eina_convert_fp)
+{
+ _eina_convert_fp_check(1.0, 0x0000000100000000, 6);
+ _eina_convert_fp_check(0.5, 0x0000000080000000, 8);
+ _eina_convert_fp_check(0.625, 0x00000000a0000000, 8);
+ _eina_convert_fp_check(256.0, 0x0000010000000000, 6);
+ _eina_convert_fp_check(0.5, 0x0000000080000000, 8);
+ _eina_convert_fp_check(128.625, 0x00000080a0000000, 10);
+}
+END_TEST
+
+void
+eina_test_convert(TCase *tc)
+{
+ tcase_add_test(tc, eina_convert_simple);
+ tcase_add_test(tc, eina_convert_double);
+ tcase_add_test(tc, eina_convert_fp);
+}
diff --git a/src/tests/eina/eina_test_counter.c b/src/tests/eina/eina_test_counter.c
new file mode 100644
index 000000000..4d956fd35
--- /dev/null
+++ b/src/tests/eina/eina_test_counter.c
@@ -0,0 +1,198 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+#include "eina_safety_checks.h"
+
+#ifdef EINA_SAFETY_CHECKS
+struct log_ctx {
+ const char *msg;
+ const char *fnc;
+ Eina_Bool did;
+};
+
+/* tests should not output on success, just uncomment this for debugging */
+//#define SHOW_LOG 1
+
+static void
+_eina_test_safety_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ va_list cp_args;
+ const char *str;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+
+ ck_assert_int_eq(level, EINA_LOG_LEVEL_ERR);
+ ck_assert_str_eq(fmt, "%s");
+ ck_assert_str_eq(ctx->msg, str);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+#endif
+
+START_TEST(eina_counter_simple)
+{
+ Eina_Counter *cnt;
+ char *dump;
+ int i;
+
+ eina_init();
+
+ cnt = eina_counter_new("eina_test");
+ fail_if(!cnt);
+
+ eina_counter_start(cnt);
+
+ for (i = 0; i < 100000; ++i)
+ {
+ void *tmp = malloc(sizeof(long int));
+ free(tmp);
+ }
+
+ eina_counter_stop(cnt, i);
+
+ eina_counter_start(cnt);
+
+ for (i = 0; i < 200000; ++i)
+ {
+ void *tmp = malloc(sizeof(long int));
+ free(tmp);
+ }
+
+ eina_counter_stop(cnt, i);
+
+ dump = eina_counter_dump(cnt);
+ fail_if(!dump);
+
+ /* TODO: parse dump and check if it's right */
+ fprintf(stderr, "%s", dump);
+
+ free(dump);
+
+ eina_counter_free(cnt);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_counter_break)
+{
+ Eina_Counter *cnt;
+
+ eina_init();
+
+ cnt = eina_counter_new("eina_test");
+ fail_if(!cnt);
+
+ eina_counter_stop(cnt, 10);
+
+ eina_counter_free(cnt);
+
+#ifdef EINA_SAFETY_CHECKS
+ {
+ struct log_ctx ctx;
+ char *dump;
+
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_counter_new",
+ "safety check failed: name == NULL");
+ cnt = eina_counter_new(NULL);
+ fail_if(cnt);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_counter_free",
+ "safety check failed: counter == NULL");
+ eina_counter_free(NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_counter_start",
+ "safety check failed: counter == NULL");
+ eina_counter_start(NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_counter_stop",
+ "safety check failed: counter == NULL");
+ eina_counter_stop(NULL, 0);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_counter_dump",
+ "safety check failed: counter == NULL");
+ dump = eina_counter_dump(NULL);
+ fail_if(dump);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+ }
+#endif
+
+ eina_shutdown();
+}
+END_TEST
+
+void eina_test_counter(TCase *tc)
+{
+ tcase_add_test(tc, eina_counter_simple);
+ tcase_add_test(tc, eina_counter_break);
+}
+
diff --git a/src/tests/eina/eina_test_error.c b/src/tests/eina/eina_test_error.c
new file mode 100644
index 000000000..57f69504c
--- /dev/null
+++ b/src/tests/eina/eina_test_error.c
@@ -0,0 +1,243 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+#define TEST_TEXT "The big test\n"
+
+struct log_ctx {
+ const char *msg;
+ const char *fnc;
+ Eina_Bool did;
+};
+
+/* tests should not output on success, just uncomment this for debugging */
+//#define SHOW_LOG 1
+
+static void
+_eina_test_safety_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ va_list cp_args;
+ const char *str;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+
+ ck_assert_int_eq(level, EINA_LOG_LEVEL_ERR);
+ ck_assert_str_eq(fmt, "%s");
+ ck_assert_str_eq(ctx->msg, str);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+
+START_TEST(eina_error_errno)
+{
+ int test;
+
+ setenv("EINA_ERROR_LEVEL", "1", 0);
+
+ eina_init();
+
+ test = eina_error_msg_register(TEST_TEXT);
+ fail_if(!eina_error_msg_get(test));
+ fail_if(strcmp(eina_error_msg_get(test), TEST_TEXT) != 0);
+
+ eina_error_set(test);
+ fail_if(eina_error_get() != test);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_error_test_find)
+{
+ int test, r;
+ const char *str;
+
+ eina_init();
+
+ test = eina_error_msg_register(TEST_TEXT);
+ ck_assert_int_ne(test, 0);
+
+ str = eina_error_msg_get(test);
+ fail_unless(str != NULL);
+ ck_assert_str_eq(str, TEST_TEXT);
+
+ eina_error_set(test);
+ fail_if(eina_error_get() != test);
+
+ r = eina_error_find(TEST_TEXT);
+ ck_assert_int_eq(r, test);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_error_test_modify)
+{
+ int test, r;
+ const char *str, smsg[] = "Do not copy this string";
+
+ eina_init();
+
+ test = eina_error_msg_register("Some Test Error");
+ ck_assert_int_ne(test, 0);
+
+ str = eina_error_msg_get(test);
+ fail_unless(str != NULL);
+ ck_assert_str_eq(str, "Some Test Error");
+
+ eina_error_set(test);
+ fail_if(eina_error_get() != test);
+
+ fail_unless(eina_error_msg_modify(test, "ABCDE"));
+
+ r = eina_error_find("ABCDE");
+ ck_assert_int_eq(r, test);
+
+ test = eina_error_msg_static_register(smsg);
+ ck_assert_int_ne(test, 0);
+
+ str = eina_error_msg_get(test);
+ fail_unless(str != NULL);
+ fail_unless(str == smsg);
+
+ fail_unless(eina_error_msg_modify(test, "Change that!"));
+ r = eina_error_find("Change that!");
+ ck_assert_int_eq(r, test);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_error_test_lots)
+{
+ char buf[64];
+ int codes[512];
+ unsigned int i;
+
+ eina_init();
+
+ for (i = 0; i < sizeof(codes)/sizeof(codes[0]); i++)
+ {
+ snprintf(buf, sizeof(buf), "myerr-%d", i);
+ codes[i] = eina_error_msg_register(buf);
+ ck_assert_int_ne(codes[i], 0);
+ }
+
+ for (i = 0; i < sizeof(codes)/sizeof(codes[0]); i++)
+ {
+ int found;
+
+ snprintf(buf, sizeof(buf), "myerr-%d", i);
+
+ found = eina_error_find(buf);
+ ck_assert_int_eq(codes[i], found);
+ }
+
+ eina_shutdown();
+}
+END_TEST
+
+#ifdef EINA_SAFETY_CHECKS
+START_TEST(eina_error_test_failures)
+{
+ struct log_ctx ctx;
+
+ eina_init();
+
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+
+ TEST_MAGIC_SAFETY("eina_error_msg_register",
+ "safety check failed: msg == NULL");
+ ck_assert_int_eq(eina_error_msg_register(NULL), 0);
+ fail_unless(ctx.did);
+
+ TEST_MAGIC_SAFETY("eina_error_msg_static_register",
+ "safety check failed: msg == NULL");
+ ck_assert_int_eq(eina_error_msg_static_register(NULL), 0);
+ fail_unless(ctx.did);
+
+ ck_assert_int_eq(eina_error_msg_modify(0, "X"), EINA_FALSE);
+ ck_assert_int_eq(eina_error_msg_modify(4096, "X"), EINA_FALSE);
+
+ TEST_MAGIC_SAFETY("eina_error_msg_modify",
+ "safety check failed: msg == NULL");
+ ck_assert_int_eq(eina_error_msg_modify(EINA_ERROR_OUT_OF_MEMORY, NULL),
+ EINA_FALSE);
+ fail_unless(ctx.did);
+
+ ck_assert_str_eq(eina_error_msg_get(EINA_ERROR_OUT_OF_MEMORY),
+ "Out of memory");
+
+ TEST_MAGIC_SAFETY("eina_error_find",
+ "safety check failed: msg == NULL");
+ ck_assert_int_eq(eina_error_find(NULL), 0);
+ fail_unless(ctx.did);
+
+ ck_assert_int_eq(eina_error_find("Non-existent Error..."), 0);
+
+ fail_if(eina_error_msg_get(0));
+ fail_if(eina_error_msg_get(4096));
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+
+ eina_shutdown();
+}
+END_TEST
+#endif
+
+void
+eina_test_error(TCase *tc)
+{
+ tcase_add_test(tc, eina_error_errno);
+ tcase_add_test(tc, eina_error_test_find);
+ tcase_add_test(tc, eina_error_test_modify);
+ tcase_add_test(tc, eina_error_test_lots);
+#ifdef EINA_SAFETY_CHECKS
+ tcase_add_test(tc, eina_error_test_failures);
+#endif
+}
diff --git a/src/tests/eina/eina_test_file.c b/src/tests/eina/eina_test_file.c
new file mode 100644
index 000000000..a3ba99869
--- /dev/null
+++ b/src/tests/eina/eina_test_file.c
@@ -0,0 +1,142 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+#include "eina_safety_checks.h"
+
+#ifdef EINA_SAFETY_CHECKS
+struct log_ctx {
+ const char *msg;
+ const char *fnc;
+ Eina_Bool did;
+};
+
+/* tests should not output on success, just uncomment this for debugging */
+//#define SHOW_LOG 1
+
+static void
+_eina_test_safety_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ va_list cp_args;
+ const char *str;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+
+ ck_assert_int_eq(level, EINA_LOG_LEVEL_ERR);
+ ck_assert_str_eq(fmt, "%s");
+ ck_assert_str_eq(ctx->msg, str);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+#endif
+
+
+START_TEST(eina_file_split_simple)
+{
+ Eina_Array *ea;
+
+ eina_init();
+
+#ifdef EINA_SAFETY_CHECKS
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ struct log_ctx ctx;
+
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+ TEST_MAGIC_SAFETY("eina_file_split", "safety check failed: path == NULL");
+ ea = eina_file_split(NULL);
+ fail_if(ea);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+#undef TEST_MAGIC_SAFETY
+#endif
+
+#ifdef _WIN32
+ ea = eina_file_split(strdup("\\this\\is\\a\\small\\test"));
+#else
+ ea = eina_file_split(strdup("/this/is/a/small/test"));
+#endif
+
+ fail_if(!ea);
+ fail_if(eina_array_count(ea) != 5);
+ fail_if(strcmp(eina_array_data_get(ea, 0), "this"));
+ fail_if(strcmp(eina_array_data_get(ea, 1), "is"));
+ fail_if(strcmp(eina_array_data_get(ea, 2), "a"));
+ fail_if(strcmp(eina_array_data_get(ea, 3), "small"));
+ fail_if(strcmp(eina_array_data_get(ea, 4), "test"));
+
+ eina_array_free(ea);
+
+#ifdef _WIN32
+ ea =
+ eina_file_split(strdup(
+ "this\\\\is\\\\\\a \\more\\complex\\\\\\case\\\\\\"));
+#else
+ ea = eina_file_split(strdup("this//is///a /more/complex///case///"));
+#endif
+
+ fail_if(!ea);
+ fail_if(eina_array_count(ea) != 6);
+ fail_if(strcmp(eina_array_data_get(ea, 0), "this"));
+ fail_if(strcmp(eina_array_data_get(ea, 1), "is"));
+ fail_if(strcmp(eina_array_data_get(ea, 2), "a "));
+ fail_if(strcmp(eina_array_data_get(ea, 3), "more"));
+ fail_if(strcmp(eina_array_data_get(ea, 4), "complex"));
+ fail_if(strcmp(eina_array_data_get(ea, 5), "case"));
+
+ eina_array_free(ea);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_file(TCase *tc)
+{
+ tcase_add_test(tc, eina_file_split_simple);
+}
+
diff --git a/src/tests/eina/eina_test_fp.c b/src/tests/eina/eina_test_fp.c
new file mode 100644
index 000000000..bdb31000a
--- /dev/null
+++ b/src/tests/eina/eina_test_fp.c
@@ -0,0 +1,93 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2010 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(eina_fp_cos)
+{
+ Eina_F32p32 fc;
+ Eina_F32p32 fl;
+ Eina_F32p32 step;
+ Eina_F32p32 fresult;
+ double dc;
+ double dresult;
+ double delta;
+
+ fail_if(!eina_init());
+
+ fl = eina_f32p32_scale(EINA_F32P32_PI, 4);
+ step = eina_f32p32_div(fl, eina_f32p32_int_from(2048));
+
+ for (fc = 0; fc < fl; fc += step)
+ {
+ fresult = eina_f32p32_cos(fc);
+ dc = eina_f32p32_double_to(fc);
+ dresult = cos(dc);
+
+ delta = fabs(dresult - eina_f32p32_double_to(fresult));
+ fail_if(delta > 0.005);
+ }
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_fp_sin)
+{
+ Eina_F32p32 fc;
+ Eina_F32p32 fl;
+ Eina_F32p32 step;
+ Eina_F32p32 fresult;
+ double dc;
+ double dresult;
+ double delta;
+
+ fail_if(!eina_init());
+
+ fl = eina_f32p32_scale(EINA_F32P32_PI, 4);
+ step = eina_f32p32_div(fl, eina_f32p32_int_from(2048));
+
+ for (fc = 0; fc < fl; fc += step)
+ {
+ fresult = eina_f32p32_sin(fc);
+ dc = eina_f32p32_double_to(fc);
+ dresult = sin(dc);
+
+ delta = fabs(dresult - eina_f32p32_double_to(fresult));
+ fail_if(delta > 0.005);
+ }
+
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_fp(TCase *tc)
+{
+ tcase_add_test(tc, eina_fp_cos);
+ tcase_add_test(tc, eina_fp_sin);
+}
diff --git a/src/tests/eina/eina_test_hash.c b/src/tests/eina/eina_test_hash.c
new file mode 100644
index 000000000..aeeb655e7
--- /dev/null
+++ b/src/tests/eina/eina_test_hash.c
@@ -0,0 +1,206 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static Eina_Bool
+eina_foreach_check(__UNUSED__ const Eina_Hash *hash,
+ const void *key,
+ void *data,
+ __UNUSED__ void *fdata)
+{
+ int *j = data;
+ int i;
+
+ if (strlen(key) <= 0)
+ return EINA_TRUE;
+
+ i = atoi(key);
+ fail_if(i != *j);
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_hash_simple)
+{
+ Eina_Hash *hash = NULL;
+ int *test;
+ int array[] = { 1, 42, 4, 5, 6 };
+
+ /* As mempool is already initialized and it use hash, we should have 2 init. */
+ fail_if(eina_init() != 2);
+
+ hash = eina_hash_string_superfast_new(NULL);
+ fail_if(hash == NULL);
+
+ fail_if(eina_hash_add(hash, "1", &array[0]) != EINA_TRUE);
+ fail_if(eina_hash_add(hash, "42", &array[1]) != EINA_TRUE);
+ fail_if(eina_hash_direct_add(hash, "4", &array[2]) != EINA_TRUE);
+ fail_if(eina_hash_direct_add(hash, "5", &array[3]) != EINA_TRUE);
+ fail_if(eina_hash_add(hash, "", "") != EINA_TRUE);
+
+ test = eina_hash_find(hash, "4");
+ fail_if(!test);
+ fail_if(*test != 4);
+
+ test = eina_hash_find(hash, "42");
+ fail_if(!test);
+ fail_if(*test != 42);
+
+ eina_hash_foreach(hash, eina_foreach_check, NULL);
+
+ test = eina_hash_modify(hash, "5", &array[4]);
+ fail_if(!test);
+ fail_if(*test != 5);
+
+ test = eina_hash_find(hash, "5");
+ fail_if(!test);
+ fail_if(*test != 6);
+
+ fail_if(eina_hash_population(hash) != 5);
+
+ fail_if(eina_hash_find(hash, "120") != NULL);
+
+ fail_if(eina_hash_del(hash, "5", NULL) != EINA_TRUE);
+ fail_if(eina_hash_find(hash, "5") != NULL);
+
+ fail_if(eina_hash_del(hash, NULL, &array[2]) != EINA_TRUE);
+ fail_if(eina_hash_find(hash, "4") != NULL);
+
+ fail_if(eina_hash_del(hash, NULL, &array[2]) != EINA_FALSE);
+
+ fail_if(eina_hash_del(hash, "1", NULL) != EINA_TRUE);
+ fail_if(eina_hash_del(hash, "42", NULL) != EINA_TRUE);
+
+ eina_hash_free(hash);
+
+ /* Same comment as eina_init */
+ fail_if(eina_shutdown() != 1);
+}
+END_TEST
+
+START_TEST(eina_hash_extended)
+{
+ Eina_Hash *hash = NULL;
+ int i;
+
+ fail_if(eina_init() != 2);
+
+ hash = eina_hash_string_djb2_new(NULL);
+ fail_if(hash == NULL);
+
+ fail_if(eina_hash_direct_add(hash, "42", "42") != EINA_TRUE);
+
+ for (i = 43; i < 3043; ++i)
+ {
+ char *tmp = malloc(10);
+ fail_if(!tmp);
+ eina_convert_itoa(i, tmp);
+ fail_if(eina_hash_direct_add(hash, tmp, tmp) != EINA_TRUE);
+ }
+
+ fail_if(eina_hash_find(hash, "42") == NULL);
+
+ eina_hash_free(hash);
+
+ fail_if(eina_shutdown() != 1);
+}
+END_TEST
+
+START_TEST(eina_hash_double_item)
+{
+ Eina_Hash *hash = NULL;
+ int i[] = { 7, 7 };
+ int *test;
+
+ fail_if(eina_init() != 2);
+
+ hash = eina_hash_string_superfast_new(NULL);
+ fail_if(hash == NULL);
+
+ fail_if(eina_hash_add(hash, "7", &i[0]) != EINA_TRUE);
+ fail_if(eina_hash_add(hash, "7", &i[1]) != EINA_TRUE);
+
+ fail_if(eina_hash_del(hash, "7", &i[1]) != EINA_TRUE);
+ test = eina_hash_find(hash, "7");
+ fail_if(test != &i[0]);
+
+ eina_hash_free(hash);
+
+ fail_if(eina_shutdown() != 1);
+}
+END_TEST
+
+START_TEST(eina_hash_all_int)
+{
+ Eina_Hash *hash;
+ int64_t j[] = { 4321312301243122, 6, 7, 128 };
+ int i[] = { 42, 6, 7, 0 };
+ int64_t *test2;
+ int *test;
+ int it;
+
+ fail_if(eina_init() != 2);
+
+ hash = eina_hash_int32_new(NULL);
+ fail_if(hash == NULL);
+
+ for (it = 0; it < 4; ++it)
+ fail_if(eina_hash_add(hash, &i[it], &i[it]) != EINA_TRUE);
+
+ fail_if(eina_hash_del(hash, &i[1], &i[1]) != EINA_TRUE);
+ test = eina_hash_find(hash, &i[2]);
+ fail_if(test != &i[2]);
+
+ test = eina_hash_find(hash, &i[3]);
+ fail_if(test != &i[3]);
+
+ eina_hash_free(hash);
+
+ hash = eina_hash_int64_new(NULL);
+ fail_if(hash == NULL);
+
+ for (it = 0; it < 4; ++it)
+ fail_if(eina_hash_add(hash, &j[it], &j[it]) != EINA_TRUE);
+
+ fail_if(eina_hash_del(hash, &j[1], &j[1]) != EINA_TRUE);
+ test2 = eina_hash_find(hash, &j[0]);
+ fail_if(test2 != &j[0]);
+
+ eina_hash_free(hash);
+
+ fail_if(eina_shutdown() != 1);
+}
+END_TEST
+
+void eina_test_hash(TCase *tc)
+{
+ tcase_add_test(tc, eina_hash_simple);
+ tcase_add_test(tc, eina_hash_extended);
+ tcase_add_test(tc, eina_hash_double_item);
+ tcase_add_test(tc, eina_hash_all_int);
+}
diff --git a/src/tests/eina/eina_test_inarray.c b/src/tests/eina/eina_test_inarray.c
new file mode 100644
index 000000000..5f33f4710
--- /dev/null
+++ b/src/tests/eina/eina_test_inarray.c
@@ -0,0 +1,401 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2012 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(eina_inarray_test_simple)
+{
+ const int test_members = 5;
+ Eina_Inarray *array;
+ int i, pos, *member;
+ const struct spec {
+ int pos, value;
+ } *s, specs[] = {
+ {test_members, 1234},
+ {5, 0x1337},
+ {0, 0xbeef},
+ {-1, -1}
+ };
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(int), 2);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < test_members; i++)
+ {
+ pos = eina_inarray_push(array, &i);
+ fail_unless(pos == i);
+ }
+ fail_unless(eina_inarray_count(array) == (unsigned)test_members);
+
+ for (i = 0; i < test_members; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i);
+ }
+
+ for (s = specs; s->pos >= 0; s++)
+ {
+ fail_unless(eina_inarray_insert_at(array, s->pos, &s->value));
+
+ for (i = 0; i < s->pos; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i);
+ }
+ member = eina_inarray_nth(array, s->pos);
+ fail_unless(*member == s->value);
+ for (i = s->pos + 1; i < test_members + 1; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i - 1);
+ }
+
+ fail_unless(eina_inarray_remove_at(array, s->pos));
+ for (i = 0; i < test_members; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i);
+ }
+ }
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_inarray_test_alloc_at)
+{
+ Eina_Inarray *array;
+ int *member;
+ int i;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(int), 2);
+ fail_unless(array != NULL);
+
+ member = eina_inarray_alloc_at(array, 0, 4);
+ fail_unless(member != NULL);
+ fail_unless(eina_inarray_count(array) == 4);
+
+ for (i = 0; i < 4; i++)
+ member[i] = i + 2;
+
+ member = eina_inarray_alloc_at(array, 0, 2);
+ fail_unless(member != NULL);
+ fail_unless(eina_inarray_count(array) == 6);
+ for (i = 0; i < 2; i++)
+ member[i] = i;
+
+ member = eina_inarray_alloc_at(array, 6, 2);
+ fail_unless(member != NULL);
+ fail_unless(eina_inarray_count(array) == 8);
+ for (i = 0; i < 2; i++)
+ member[i] = i + 6;
+
+ member = array->members;
+ for (i = 0; i < 8; i++)
+ fail_unless(member[i] == i);
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+static const short rand_numbers[] = {
+ 9, 0, 2, 3, 6, 5, 4, 7, 8, 1, 10
+};
+static const int numbers_count = sizeof(rand_numbers)/sizeof(rand_numbers[0]);
+
+static void
+show_sort_array(const Eina_Inarray *array)
+{
+ int i, len = eina_inarray_count(array);
+ printf("array with %d members:\n", len);
+ for (i = 0; i < len; i++)
+ {
+ short *member = eina_inarray_nth(array, i);
+ printf("\tarray[%2d]=%5hd\n", i, *member);
+ }
+}
+
+static Eina_Bool
+check_short_sorted(const Eina_Inarray *array)
+{
+ int i;
+ for (i = 0; i < numbers_count; i++)
+ {
+ short *member = eina_inarray_nth(array, i);
+ if (*member != (short)i)
+ {
+ show_sort_array(array);
+ fprintf(stderr, "not sorted at %d: %hd\n", i, *member);
+ return EINA_FALSE;
+ }
+ }
+ return EINA_TRUE;
+}
+
+static int
+short_cmp(const void *pa, const void *pb)
+{
+ const short *a = pa, *b = pb;
+ return *a - *b;
+}
+
+START_TEST(eina_inarray_test_insert_sort)
+{
+ Eina_Inarray *array;
+ int i, pos;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ /* insert sorted and already sorted sequence */
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ pos = eina_inarray_insert(array, &val, short_cmp);
+ fail_unless(pos == (int)val);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ pos = eina_inarray_insert_sorted(array, &val, short_cmp);
+ fail_unless(pos == (int)val);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ /* insert sorted the reverse sequence */
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = numbers_count - i - 1;
+ pos = eina_inarray_insert(array, &val, short_cmp);
+ fail_unless(pos == 0);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = numbers_count - i - 1;
+ pos = eina_inarray_insert_sorted(array, &val, short_cmp);
+ fail_unless(pos == 0);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ /* insert sorted random numbers */
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = rand_numbers[i];
+ eina_inarray_insert(array, &val, short_cmp);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = rand_numbers[i];
+ eina_inarray_insert_sorted(array, &val, short_cmp);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_inarray_test_sort)
+{
+ Eina_Inarray *array;
+ int i;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = rand_numbers[i];
+ eina_inarray_push(array, &val);
+ }
+ eina_inarray_sort(array, short_cmp);
+ fail_unless(check_short_sorted(array));
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_inarray_test_reverse)
+{
+ Eina_Inarray *array;
+ int i;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ eina_inarray_push(array, &val);
+ }
+ eina_inarray_reverse(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short *member = eina_inarray_nth(array, i);
+ fail_unless(*member == (numbers_count - i - 1));
+ }
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Bool
+array_foreach(const void *array __UNUSED__, void *p, void *user_data __UNUSED__)
+{
+ short *member = p;
+ int *i = user_data;
+ fail_unless(*i == *member);
+ (*i)++;
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+array_foreach_stop_2nd(const void *array __UNUSED__, void *p, void *user_data __UNUSED__)
+{
+ short *member = p;
+ int *i = user_data;
+ fail_unless(*i == *member);
+ if (*i == 1)
+ return EINA_FALSE;
+ (*i)++;
+ return EINA_TRUE;
+}
+
+START_TEST(eina_inarray_test_itr)
+{
+ Eina_Inarray *array;
+ Eina_Iterator *it;
+ Eina_Accessor *ac;
+ short *member;
+ int i;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ eina_inarray_push(array, &val);
+ }
+ i = 0;
+ EINA_INARRAY_FOREACH(array, member)
+ {
+ fail_unless(*member == i);
+ i++;
+ }
+ fail_unless(i == numbers_count);
+
+ i--;
+ EINA_INARRAY_REVERSE_FOREACH(array, member)
+ {
+ fail_unless(*member == i);
+ i--;
+ }
+ fail_unless(i == -1);
+
+ i = 0;
+ fail_unless(eina_inarray_foreach(array, array_foreach, &i));
+ fail_unless(i == numbers_count);
+
+ i = 0;
+ fail_if(eina_inarray_foreach(array, array_foreach_stop_2nd, &i));
+ fail_unless(i == 1);
+
+ it = eina_inarray_iterator_new(array);
+ fail_unless(it != NULL);
+ i = 0;
+ EINA_ITERATOR_FOREACH(it, member)
+ {
+ fail_unless(*member == i);
+ i++;
+ }
+ fail_unless(i == numbers_count);
+ eina_iterator_free(it);
+
+ it = eina_inarray_iterator_reversed_new(array);
+ fail_unless(it != NULL);
+ i--;
+ EINA_ITERATOR_FOREACH(it, member)
+ {
+ fail_unless(*member == i);
+ i--;
+ }
+ fail_unless(i == -1);
+ eina_iterator_free(it);
+
+ ac = eina_inarray_accessor_new(array);
+ fail_unless(ac != NULL);
+ for (i = 0; i < numbers_count; i++)
+ {
+ fail_unless(eina_accessor_data_get(ac, i, (void **)&member));
+ fail_unless(*member == i);
+ }
+ fail_unless(i == numbers_count);
+ eina_accessor_free(ac);
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_inarray(TCase *tc)
+{
+ tcase_add_test(tc, eina_inarray_test_simple);
+ tcase_add_test(tc, eina_inarray_test_alloc_at);
+ tcase_add_test(tc, eina_inarray_test_insert_sort);
+ tcase_add_test(tc, eina_inarray_test_sort);
+ tcase_add_test(tc, eina_inarray_test_reverse);
+ tcase_add_test(tc, eina_inarray_test_itr);
+}
diff --git a/src/tests/eina/eina_test_inlist.c b/src/tests/eina/eina_test_inlist.c
new file mode 100644
index 000000000..a8631e708
--- /dev/null
+++ b/src/tests/eina/eina_test_inlist.c
@@ -0,0 +1,421 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+#include "eina_safety_checks.h"
+
+typedef struct _Eina_Test_Inlist Eina_Test_Inlist;
+struct _Eina_Test_Inlist
+{
+ int i;
+ EINA_INLIST;
+};
+
+#ifdef EINA_SAFETY_CHECKS
+struct log_ctx {
+ const char *msg;
+ const char *fnc;
+ Eina_Bool did;
+};
+
+/* tests should not output on success, just uncomment this for debugging */
+//#define SHOW_LOG 1
+
+static void
+_eina_test_safety_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ va_list cp_args;
+ const char *str;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+
+ ck_assert_int_eq(level, EINA_LOG_LEVEL_ERR);
+ ck_assert_str_eq(fmt, "%s");
+ ck_assert_str_eq(ctx->msg, str);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+#endif
+
+static Eina_Test_Inlist *
+_eina_test_inlist_build(int i)
+{
+ Eina_Test_Inlist *tmp;
+
+ tmp = malloc(sizeof(Eina_Test_Inlist));
+ fail_if(!tmp);
+ tmp->i = i;
+
+ return tmp;
+}
+
+START_TEST(eina_inlist_simple)
+{
+ Eina_Inlist *lst = NULL;
+ Eina_Test_Inlist *tmp;
+ Eina_Test_Inlist *prev;
+ int i = 0;
+#ifdef EINA_SAFETY_CHECKS
+ Eina_Inlist *bkp;
+ struct log_ctx ctx;
+#endif
+
+ fail_if(!eina_init());
+
+ tmp = _eina_test_inlist_build(42);
+ lst = eina_inlist_append(lst, EINA_INLIST_GET(tmp));
+ fail_if(!lst);
+
+ lst = eina_inlist_remove(lst, EINA_INLIST_GET(tmp));
+ lst = eina_inlist_prepend(lst, EINA_INLIST_GET(tmp));
+
+ tmp = _eina_test_inlist_build(1664);
+ lst = eina_inlist_append_relative(lst, EINA_INLIST_GET(tmp), lst);
+ fail_if(!lst);
+ fail_if(EINA_INLIST_CONTAINER_GET(lst, Eina_Test_Inlist)->i != 42);
+
+ prev = tmp;
+ tmp = _eina_test_inlist_build(3227);
+ lst = eina_inlist_prepend_relative(lst, EINA_INLIST_GET(
+ tmp), EINA_INLIST_GET(prev));
+ fail_if(!lst);
+ fail_if(EINA_INLIST_CONTAINER_GET(lst, Eina_Test_Inlist)->i != 42);
+
+ lst = eina_inlist_remove(lst, EINA_INLIST_GET(tmp));
+
+ lst = eina_inlist_append_relative(lst, EINA_INLIST_GET(tmp), lst);
+ lst = eina_inlist_remove(lst, EINA_INLIST_GET(tmp));
+
+ lst = eina_inlist_prepend_relative(lst, EINA_INLIST_GET(tmp), lst);
+
+ tmp = _eina_test_inlist_build(27);
+ lst = eina_inlist_prepend_relative(lst, EINA_INLIST_GET(tmp), NULL);
+
+ tmp = _eina_test_inlist_build(81);
+ lst = eina_inlist_append_relative(lst, EINA_INLIST_GET(tmp), NULL);
+
+ EINA_INLIST_FOREACH(lst, tmp)
+ {
+ switch (i)
+ {
+ case 0: fail_if(tmp->i != 27); break;
+
+ case 1: fail_if(tmp->i != 3227); break;
+
+ case 2: fail_if(tmp->i != 42); break;
+
+ case 3: fail_if(tmp->i != 1664); break;
+
+ case 4: fail_if(tmp->i != 81); break;
+ }
+
+ ++i;
+ }
+
+#ifdef EINA_SAFETY_CHECKS
+ bkp = lst;
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ {
+ Eina_Inlist *tmp2;
+
+ TEST_MAGIC_SAFETY("eina_inlist_remove",
+ "safety check failed: list == NULL");
+
+ tmp2 = eina_inlist_remove(NULL, EINA_INLIST_GET(tmp));
+ fail_if(tmp2 != NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+ }
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_remove",
+ "safety check failed: item == NULL");
+ lst = eina_inlist_remove(lst, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_append",
+ "safety check failed: new_l == NULL");
+ lst = eina_inlist_append(lst, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_append_relative",
+ "safety check failed: new_l == NULL");
+ lst = eina_inlist_append_relative(lst, NULL, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_prepend",
+ "safety check failed: new_l == NULL");
+ lst = eina_inlist_prepend(lst, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_prepend_relative",
+ "safety check failed: new_l == NULL");
+ lst = eina_inlist_prepend_relative(lst, NULL, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_find",
+ "safety check failed: item == NULL");
+ lst = eina_inlist_find(lst, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_demote",
+ "safety check failed: list == NULL");
+ lst = eina_inlist_demote(NULL, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_demote",
+ "safety check failed: item == NULL");
+ lst = eina_inlist_demote((void*)1L, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+ lst = NULL;
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_promote",
+ "safety check failed: list == NULL");
+ lst = eina_inlist_promote(NULL, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_promote",
+ "safety check failed: item == NULL");
+ lst = eina_inlist_promote((void*)1L, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+ lst = NULL;
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_sorted_insert",
+ "safety check failed: item == NULL");
+ lst = eina_inlist_sorted_insert(NULL, NULL, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_inlist_sorted_insert",
+ "safety check failed: func == NULL");
+ lst = eina_inlist_sorted_insert(NULL, (void*)1L, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+ lst = NULL;
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+ lst = bkp;
+#endif
+
+ tmp = EINA_INLIST_CONTAINER_GET(lst, Eina_Test_Inlist);
+ lst = eina_inlist_demote(lst, lst);
+ fail_if(EINA_INLIST_CONTAINER_GET(lst, Eina_Test_Inlist) == tmp);
+
+ lst = eina_inlist_promote(lst, EINA_INLIST_GET(tmp));
+ fail_if(lst != EINA_INLIST_GET(tmp));
+
+ tmp = EINA_INLIST_CONTAINER_GET(eina_inlist_find(lst, EINA_INLIST_GET(
+ prev)), Eina_Test_Inlist);
+ lst = eina_inlist_remove(lst, EINA_INLIST_GET(tmp));
+ prev = (Eina_Test_Inlist *)eina_inlist_find(lst, EINA_INLIST_GET(tmp));
+ tmp = prev ? EINA_INLIST_CONTAINER_GET(prev, Eina_Test_Inlist) : NULL;
+ fail_if(tmp != NULL);
+
+ while (lst)
+ lst = eina_inlist_remove(lst, lst);
+
+ eina_shutdown();
+}
+END_TEST
+
+typedef struct _Eina_Test_Inlist_Sorted Eina_Test_Inlist_Sorted;
+struct _Eina_Test_Inlist_Sorted
+{
+ EINA_INLIST;
+
+ int value;
+};
+
+static int
+_eina_test_inlist_cmp(const void *d1, const void *d2)
+{
+ const Eina_Test_Inlist_Sorted *t1 = d1;
+ const Eina_Test_Inlist_Sorted *t2 = d2;
+
+ return t1->value - t2->value;
+}
+
+static void
+_eina_test_inlist_check(const Eina_Inlist *list)
+{
+ const Eina_Test_Inlist_Sorted *t;
+ int last_value = 0;
+
+ EINA_INLIST_FOREACH(list, t)
+ {
+ fail_if(t->value < last_value);
+ last_value = t->value;
+ }
+}
+
+START_TEST(eina_inlist_sorted)
+{
+ Eina_Test_Inlist_Sorted *tmp;
+ Eina_Inlist *list = NULL;
+ Eina_Inlist *sorted = NULL;
+ int i;
+
+ fail_if(!eina_init());
+
+ srand(time(NULL));
+
+ for (i = 0; i < 2000; ++i)
+ {
+ tmp = malloc(sizeof (Eina_Test_Inlist_Sorted));
+ if (!tmp) continue ;
+
+ tmp->value = rand();
+
+ list = eina_inlist_prepend(list, EINA_INLIST_GET(tmp));
+ }
+
+ list = eina_inlist_sort(list, _eina_test_inlist_cmp);
+
+ _eina_test_inlist_check(list);
+
+ EINA_INLIST_FOREACH(list, tmp)
+ tmp->value = rand();
+
+ i = 0;
+ while (list)
+ {
+ Eina_Inlist *p = list;
+
+ list = eina_inlist_remove(list, list);
+
+ sorted = eina_inlist_sorted_insert(sorted, p, _eina_test_inlist_cmp);
+ _eina_test_inlist_check(sorted);
+ }
+
+ _eina_test_inlist_check(sorted);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_inlist_sorted_state)
+{
+ Eina_Test_Inlist_Sorted *tmp;
+ Eina_Inlist_Sorted_State *state;
+ Eina_Inlist *list = NULL;
+ int i;
+
+ fail_if(!eina_init());
+
+ state = eina_inlist_sorted_state_new();
+ fail_if(!state);
+
+ for (i = 0; i < 2000; ++i)
+ {
+ tmp = malloc(sizeof (Eina_Test_Inlist_Sorted));
+ if (!tmp) continue ;
+
+ tmp->value = rand();
+
+ list = eina_inlist_sorted_state_insert(list, EINA_INLIST_GET(tmp), _eina_test_inlist_cmp, state);
+ _eina_test_inlist_check(list);
+ }
+
+ _eina_test_inlist_check(list);
+
+ eina_inlist_sorted_state_free(state);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_inlist(TCase *tc)
+{
+ tcase_add_test(tc, eina_inlist_simple);
+ tcase_add_test(tc, eina_inlist_sorted);
+ tcase_add_test(tc, eina_inlist_sorted_state);
+}
diff --git a/src/tests/eina/eina_test_iterator.c b/src/tests/eina/eina_test_iterator.c
new file mode 100644
index 000000000..84bb33693
--- /dev/null
+++ b/src/tests/eina/eina_test_iterator.c
@@ -0,0 +1,465 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static Eina_Bool
+eina_iterator_array_check(__UNUSED__ const Eina_Array *array,
+ int *data, int *fdata)
+{
+ fail_if(*fdata > *data);
+ *fdata = *data;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_iterator_array_simple)
+{
+ Eina_Iterator *it;
+ Eina_Array *ea;
+ int *tmp;
+ int i;
+
+ eina_init();
+
+ ea = eina_array_new(11);
+ fail_if(!ea);
+
+ for (i = 0; i < 200; ++i)
+ {
+ tmp = malloc(sizeof(int));
+ fail_if(!tmp);
+ *tmp = i;
+
+ eina_array_push(ea, tmp);
+ }
+
+ it = eina_array_iterator_new(ea);
+ fail_if(!it);
+
+ i = -1;
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &i);
+ fail_if(i != 199);
+
+ fail_if(eina_iterator_container_get(it) != ea);
+ fail_if(eina_iterator_next(it, (void **)&tmp) != EINA_FALSE);
+
+ eina_iterator_free(it);
+
+ eina_array_free(ea);
+
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Bool
+eina_iterator_hash_key_check(const Eina_Hash *hash,
+ const char *key,
+ __UNUSED__ void *fdata)
+{
+ fail_if(eina_hash_find(hash, key) == NULL);
+
+ return EINA_TRUE;
+}
+static Eina_Bool
+eina_iterator_hash_data_check(const Eina_Hash *hash,
+ int *data,
+ __UNUSED__ void *fdata)
+{
+ char tmp[10];
+
+ snprintf(tmp, 10, "%i", *data);
+ fail_if(eina_hash_find(hash, tmp) != data);
+
+ return EINA_TRUE;
+}
+static Eina_Bool
+eina_iterator_hash_tuple_check(__UNUSED__ const Eina_Hash *hash,
+ Eina_Hash_Tuple *tuple,
+ __UNUSED__ void *fdata)
+{
+ fail_if(atoi((char *)tuple->key) != *((int *)tuple->data));
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_iterator_hash_simple)
+{
+ Eina_Iterator *it;
+ Eina_Hash *hash;
+ int array[] = { 1, 42, 7, 8, 6 };
+
+ eina_init();
+
+ hash = eina_hash_string_superfast_new(NULL);
+ fail_if(hash == NULL);
+
+ fail_if(eina_hash_add(hash, "1", &array[0]) != EINA_TRUE);
+ fail_if(eina_hash_add(hash, "42", &array[1]) != EINA_TRUE);
+ fail_if(eina_hash_add(hash, "7", &array[2]) != EINA_TRUE);
+ fail_if(eina_hash_add(hash, "8", &array[3]) != EINA_TRUE);
+ fail_if(eina_hash_add(hash, "6", &array[4]) != EINA_TRUE);
+
+ it = eina_hash_iterator_key_new(hash);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_hash_key_check), NULL);
+ eina_iterator_free(it);
+
+ it = eina_hash_iterator_data_new(hash);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_hash_data_check), NULL);
+ eina_iterator_free(it);
+
+ it = eina_hash_iterator_tuple_new(hash);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_hash_tuple_check), NULL);
+ eina_iterator_free(it);
+
+ eina_hash_free(hash);
+
+ eina_shutdown();
+}
+END_TEST
+
+typedef struct _Eina_Test_Inlist Eina_Test_Inlist;
+struct _Eina_Test_Inlist
+{
+ EINA_INLIST;
+ int i;
+};
+
+static Eina_Test_Inlist *
+_eina_test_inlist_build(int i)
+{
+ Eina_Test_Inlist *tmp;
+
+ tmp = malloc(sizeof(Eina_Test_Inlist));
+ fail_if(!tmp);
+ tmp->i = i;
+
+ return tmp;
+}
+
+static Eina_Bool
+eina_iterator_inlist_data_check(__UNUSED__ const Eina_Inlist *in_list,
+ Eina_Test_Inlist *data,
+ int *fdata)
+{
+ switch (*fdata)
+ {
+ case 0: fail_if(data->i != 27); break;
+
+ case 1: fail_if(data->i != 42); break;
+
+ case 2: fail_if(data->i != 3227); break;
+
+ case 3: fail_if(data->i != 1664); break;
+
+ case 4: fail_if(data->i != 81); break;
+ }
+
+ (*fdata)++;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_iterator_inlist_simple)
+{
+ Eina_Inlist *lst = NULL;
+ Eina_Test_Inlist *tmp;
+ Eina_Test_Inlist *prev;
+ Eina_Iterator *it;
+ int i = 0;
+
+ tmp = _eina_test_inlist_build(42);
+ lst = eina_inlist_append(lst, EINA_INLIST_GET(tmp));
+ fail_if(!lst);
+
+ tmp = _eina_test_inlist_build(1664);
+ lst = eina_inlist_append_relative(lst, EINA_INLIST_GET(tmp), lst);
+ fail_if(!lst);
+ fail_if(((Eina_Test_Inlist *)lst)->i != 42);
+
+ prev = tmp;
+ tmp = _eina_test_inlist_build(3227);
+ lst = eina_inlist_prepend_relative(lst, EINA_INLIST_GET(
+ tmp), EINA_INLIST_GET(prev));
+ fail_if(!lst);
+ fail_if(((Eina_Test_Inlist *)lst)->i != 42);
+
+ tmp = _eina_test_inlist_build(27);
+ lst = eina_inlist_prepend_relative(lst, EINA_INLIST_GET(tmp), NULL);
+
+ tmp = _eina_test_inlist_build(81);
+ lst = eina_inlist_append_relative(lst, EINA_INLIST_GET(tmp), NULL);
+
+ it = eina_inlist_iterator_new(lst);
+ fail_if(!it);
+
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_inlist_data_check), &i);
+ eina_iterator_free(it);
+
+ fail_if(i != 5);
+}
+END_TEST
+
+static Eina_Bool
+eina_iterator_list_data_check(__UNUSED__ const Eina_List *list,
+ int *data,
+ int *fdata)
+{
+ switch (*fdata)
+ {
+ case 0: fail_if(*data != 81); break;
+
+ case 1: fail_if(*data != 7); break;
+
+ case 2: fail_if(*data != 9); break;
+
+ case 3: fail_if(*data != 6); break;
+
+ case 4: fail_if(*data != 42); break;
+
+ case 5: fail_if(*data != 1); break;
+
+ case 6: fail_if(*data != 1337); break;
+ }
+
+ (*fdata)++;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_iterator_list_simple)
+{
+ Eina_List *list = NULL;
+ Eina_Iterator *it;
+ int data[] = { 6, 9, 42, 1, 7, 1337, 81, 1664 };
+ int i = 0;
+
+ eina_init();
+
+ list = eina_list_append(list, &data[0]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend(list, &data[1]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[2]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[3]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend(list, &data[4]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[5]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend(list, &data[6]);
+ fail_if(list == NULL);
+
+ it = eina_list_iterator_new(list);
+ fail_if(!it);
+
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_list_data_check), &i);
+ eina_iterator_free(it);
+}
+END_TEST
+
+typedef struct _Eina_Rbtree_Int Eina_Rbtree_Int;
+struct _Eina_Rbtree_Int
+{
+ Eina_Rbtree node;
+ int value;
+};
+
+static Eina_Rbtree_Direction
+eina_rbtree_int_cmp(const Eina_Rbtree_Int *left, const Eina_Rbtree_Int *right)
+{
+ fail_if(!left);
+ fail_if(!right);
+
+ if (left->value < right->value)
+ return EINA_RBTREE_LEFT;
+
+ return EINA_RBTREE_RIGHT;
+}
+
+static Eina_Rbtree *
+_eina_rbtree_int_new(int value)
+{
+ Eina_Rbtree_Int *it;
+
+ it = malloc(sizeof (Eina_Rbtree_Int));
+ fail_if(!it);
+
+ it->value = value;
+
+ return &it->node;
+}
+
+static Eina_Bool
+eina_iterator_rbtree_data_check_sorted(__UNUSED__ const Eina_List *list,
+ Eina_Rbtree_Int *data,
+ int *fdata)
+{
+ switch (*fdata)
+ {
+ case 0: fail_if(data->value != 10); break;
+
+ case 1: fail_if(data->value != 27); break;
+
+ case 2: fail_if(data->value != 42); break;
+
+ case 3: fail_if(data->value != 69); break;
+
+ case 4: fail_if(data->value != 1337); break;
+ }
+
+ (*fdata)++;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+eina_iterator_rbtree_data_check_prefix(__UNUSED__ const Eina_List *list,
+ Eina_Rbtree_Int *data,
+ int *fdata)
+{
+ switch (*fdata)
+ {
+ case 0: fail_if(data->value != 27); break;
+
+ case 1: fail_if(data->value != 10); break;
+
+ case 2: fail_if(data->value != 69); break;
+
+ case 3: fail_if(data->value != 42); break;
+
+ case 4: fail_if(data->value != 1337); break;
+ }
+
+ (*fdata)++;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+eina_iterator_rbtree_data_check_postfix(__UNUSED__ const Eina_List *list,
+ Eina_Rbtree_Int *data,
+ int *fdata)
+{
+ switch (*fdata)
+ {
+ case 0: fail_if(data->value != 10); break;
+
+ case 1: fail_if(data->value != 42); break;
+
+ case 2: fail_if(data->value != 1337); break;
+
+ case 3: fail_if(data->value != 69); break;
+
+ case 4: fail_if(data->value != 27); break;
+ }
+
+ (*fdata)++;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_iterator_rbtree_simple)
+{
+ Eina_Rbtree *root = NULL;
+ Eina_Iterator *it;
+ int i;
+
+ root = eina_rbtree_inline_insert(NULL,
+ _eina_rbtree_int_new(10),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
+ fail_if(!root);
+
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(1337),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
+ fail_if(!root);
+
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(27),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
+ fail_if(!root);
+
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(69),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
+ fail_if(!root);
+
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(42),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
+ fail_if(!root);
+
+ i = 0;
+ it = eina_rbtree_iterator_prefix(root);
+ fail_if(!it);
+
+ eina_iterator_foreach(it,
+ EINA_EACH_CB(eina_iterator_rbtree_data_check_prefix),
+ &i);
+ eina_iterator_free(it);
+
+ /* This will return the item sorted. */
+ i = 0;
+ it = eina_rbtree_iterator_infix(root);
+ fail_if(!it);
+
+ eina_iterator_foreach(it,
+ EINA_EACH_CB(eina_iterator_rbtree_data_check_sorted),
+ &i);
+ eina_iterator_free(it);
+
+ i = 0;
+ it = eina_rbtree_iterator_postfix(root);
+ fail_if(!it);
+
+ eina_iterator_foreach(it,
+ EINA_EACH_CB(eina_iterator_rbtree_data_check_postfix),
+ &i);
+ eina_iterator_free(it);
+}
+END_TEST
+
+void
+eina_test_iterator(TCase *tc)
+{
+ tcase_add_test(tc, eina_iterator_array_simple);
+ tcase_add_test(tc, eina_iterator_hash_simple);
+ tcase_add_test(tc, eina_iterator_inlist_simple);
+ tcase_add_test(tc, eina_iterator_list_simple);
+ tcase_add_test(tc, eina_iterator_rbtree_simple);
+}
diff --git a/src/tests/eina/eina_test_lalloc.c b/src/tests/eina/eina_test_lalloc.c
new file mode 100644
index 000000000..13fd6078a
--- /dev/null
+++ b/src/tests/eina/eina_test_lalloc.c
@@ -0,0 +1,89 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+typedef struct _Eina_Lazy_Allocator_Test Eina_Lazy_Allocator_Test;
+struct _Eina_Lazy_Allocator_Test
+{
+ void *data;
+ int num;
+};
+
+static Eina_Bool
+_test_alloc(Eina_Lazy_Allocator_Test *elat, int num)
+{
+ if (elat->num == 10 && num == 1)
+ return EINA_FALSE;
+
+ if (elat->num == 122 && num == 128)
+ return EINA_FALSE;
+
+ elat->num += num;
+ elat->data = realloc(elat->data, elat->num);
+
+ return EINA_TRUE;
+}
+
+static void
+_test_free(Eina_Lazy_Allocator_Test *elat)
+{
+ free(elat->data);
+ elat->data = NULL;
+ elat->num = 0;
+}
+
+START_TEST(eina_lalloc_simple)
+{
+ Eina_Lazy_Allocator_Test *elat;
+ Eina_Lalloc *test;
+ int i;
+
+ elat = calloc(1, sizeof (Eina_Lazy_Allocator_Test));
+ fail_if(!elat);
+
+ test = eina_lalloc_new(elat, EINA_LALLOC_ALLOC(
+ _test_alloc), EINA_LALLOC_FREE(_test_free), 10);
+ fail_if(!test);
+
+ for (i = 0; i < 10; ++i)
+ fail_if(eina_lalloc_element_add(test) != EINA_TRUE);
+ fail_if(eina_lalloc_element_add(test) != EINA_FALSE);
+ fail_if(eina_lalloc_elements_add(test, 5) != EINA_TRUE);
+ for (i = 0; i < 21; ++i)
+ fail_if(eina_lalloc_element_add(test) != EINA_TRUE);
+
+ fail_if(eina_lalloc_elements_add(test, 50) != EINA_FALSE);
+
+ eina_lalloc_free(test);
+}
+END_TEST
+
+void
+eina_test_lalloc(TCase *tc)
+{
+ tcase_add_test(tc, eina_lalloc_simple);
+}
diff --git a/src/tests/eina/eina_test_list.c b/src/tests/eina/eina_test_list.c
new file mode 100644
index 000000000..0f48688a5
--- /dev/null
+++ b/src/tests/eina/eina_test_list.c
@@ -0,0 +1,385 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static Eina_Bool eina_list_sorted_check(const Eina_List *list)
+{
+ const Eina_List *n;
+ void *d;
+ int last = *(int *)list->data;
+
+ EINA_LIST_FOREACH(list->next, n, d)
+ {
+ int current = *(int *)d;
+ if (last > current)
+ {
+ fprintf(stderr, "list is not sorted: last=%d, current=%d\n",
+ last, current);
+ return 0;
+ }
+
+ last = current;
+ }
+
+ return 1;
+}
+
+static int eina_int_cmp(const void *a, const void *b)
+{
+ const int *ia = a;
+ const int *ib = b;
+
+ return *ia - *ib;
+}
+
+START_TEST(eina_test_simple)
+{
+ Eina_List *list = NULL;
+ Eina_List *tmp;
+ int *test1;
+ int *test2;
+ int *test3;
+ int data[] = { 6, 9, 42, 1, 7, 9, 81, 1664, 1337 };
+ int result[] = { 81, 9, 9, 7, 1 };
+ int i;
+
+ eina_init();
+
+ list = eina_list_append(list, &data[0]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend(list, &data[1]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[2]);
+ fail_if(list == NULL);
+
+ list = eina_list_remove(list, &data[0]);
+ fail_if(list == NULL);
+
+ list = eina_list_remove(list, &data[0]);
+ fail_if(list == NULL);
+
+ tmp = eina_list_data_find_list(list, &data[2]);
+ fail_if(tmp == NULL);
+
+ list = eina_list_append_relative_list(list, &data[3], tmp);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend_relative_list(list, &data[4], tmp);
+ fail_if(list == NULL);
+
+ list = eina_list_promote_list(list, tmp);
+ fail_if(list == NULL);
+
+ list = eina_list_append_relative(list, &data[5], &data[2]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend_relative(list, &data[6], &data[2]);
+ fail_if(list == NULL);
+
+ list = eina_list_remove_list(list, tmp);
+ fail_if(list == NULL);
+
+ fail_if(eina_list_data_find_list(list, &data[2]) != NULL);
+ fail_if(eina_list_data_find(list, &data[2]) != NULL);
+ fail_if(eina_list_data_find(list, &data[5]) != &data[5]);
+
+ fail_if(eina_list_count(list) != 5);
+ fail_if(eina_list_nth(list, 4) != &data[3]);
+ fail_if(eina_list_nth(list, 10) != NULL);
+ fail_if(eina_list_nth_list(list, 10) != NULL);
+
+ for (tmp = list, i = 0; tmp != NULL; tmp = eina_list_next(tmp), ++i)
+ {
+ int *d = eina_list_data_get(tmp);
+ fail_if(d == NULL);
+ fail_if(*d != result[i]);
+ }
+
+ list = eina_list_reverse(list);
+
+ for (tmp = list; tmp != NULL; tmp = eina_list_next(tmp), --i)
+ {
+ int *d = eina_list_data_get(tmp);
+ fail_if(d == NULL);
+ fail_if(*d != result[i - 1]);
+ }
+
+ list = eina_list_append_relative(list, &data[7], &data[7]);
+ fail_if(list == NULL);
+
+ list = eina_list_prepend_relative(list, &data[8], &data[8]);
+ fail_if(list == NULL);
+
+ list = eina_list_sort(list, 2, eina_int_cmp);
+
+ list = eina_list_sort(list, 2, eina_int_cmp);
+
+ test1 = eina_list_nth(list, 0);
+ test2 = eina_list_nth(list, 1);
+ test3 = eina_list_nth(list, 2);
+
+ fail_if(test1 == NULL || test2 == NULL || test3 == NULL);
+ fail_if(*test1 > *test2);
+ fail_if(*test3 == *test2);
+
+ list = eina_list_sort(list, 5, eina_int_cmp);
+
+ test1 = eina_list_nth(list, 3);
+ test2 = eina_list_nth(list, 4);
+ test3 = eina_list_nth(list, 5);
+
+ fail_if(test1 == NULL || test2 == NULL || test3 == NULL);
+ fail_if(*test1 > *test2);
+ fail_if(*test3 > *test2);
+
+ list = eina_list_append(list, &data[8]);
+ fail_if(list == NULL);
+
+ list = eina_list_append(list, &data[7]);
+ fail_if(list == NULL);
+
+ list = eina_list_sort(list, -1, eina_int_cmp);
+
+ test1 = eina_list_nth(list, 0);
+ for (tmp = list; tmp != NULL; tmp = eina_list_next(tmp))
+ {
+ int *d = eina_list_data_get(tmp);
+ fail_if(*test1 > *d);
+
+ test1 = d;
+ }
+
+ test3 = eina_list_nth(list, 5);
+ fail_if(test3 == NULL);
+
+ list = eina_list_promote_list(list, list);
+ fail_if(list == NULL);
+
+ list = eina_list_promote_list(list, eina_list_last(list));
+ fail_if(list == NULL);
+
+ test1 = eina_list_nth(list, 0);
+ test2 = eina_list_nth(list, 1);
+
+ list = eina_list_promote_list(eina_list_next(list), list);
+ fail_if(list == NULL);
+ fail_if(eina_list_data_get(list) != test1);
+ fail_if(eina_list_data_get(eina_list_next(list)) != test2);
+
+ list = eina_list_remove_list(list, list);
+ fail_if(list == NULL);
+
+ list = eina_list_remove_list(list, eina_list_last(list));
+ fail_if(list == NULL);
+
+ list = eina_list_free(list);
+ fail_if(list != NULL);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_merge)
+{
+ Eina_List *l1;
+ Eina_List *l2;
+ Eina_List *l3;
+ Eina_List *l4;
+ Eina_List *l5;
+ int data[] = { 6, 9, 42, 1, 7, 9, 81, 1664, 1337, 3, 21, 10, 0, 5, 2008 };
+ int i;
+
+ eina_init();
+
+ l1 = eina_list_append(NULL, &data[0]);
+ l1 = eina_list_append(l1, &data[1]);
+ l1 = eina_list_append(l1, &data[2]);
+ l1 = eina_list_append(l1, &data[3]);
+ fail_if(l1 == NULL);
+
+ l2 = eina_list_append(NULL, &data[4]);
+ l2 = eina_list_append(l2, &data[5]);
+ fail_if(l2 == NULL);
+
+ l1 = eina_list_merge(l1, l2);
+ fail_if(l1 == NULL);
+ fail_if(eina_list_count(l1) != 6);
+ for (i = 0, l2 = l1; ((l2 != NULL) && (i < 6)); ++i, l2 = l2->next)
+ fail_if(l2->data != &data[i]);
+ fail_if(i != 6);
+ fail_if(l2 != NULL);
+
+ eina_list_free(l1);
+
+ l1 = eina_list_append(NULL, &data[0]);
+ l1 = eina_list_append(l1, &data[1]);
+ fail_if(l1 == NULL);
+
+ l2 = eina_list_append(NULL, &data[2]);
+ l2 = eina_list_append(l2, &data[3]);
+ l2 = eina_list_append(l2, &data[4]);
+ l2 = eina_list_append(l2, &data[5]);
+ fail_if(l2 == NULL);
+
+ l1 = eina_list_merge(l1, l2);
+ fail_if(l1 == NULL);
+ fail_if(eina_list_count(l1) != 6);
+ for (i = 0, l2 = l1; ((l2 != NULL) && (i < 6)); ++i, l2 = l2->next)
+ fail_if(l2->data != &data[i]);
+ fail_if(i != 6);
+ fail_if(l2 != NULL);
+
+ l3 = eina_list_append(NULL, &data[6]);
+ l3 = eina_list_append(l3, &data[7]);
+ l3 = eina_list_append(l3, &data[8]);
+
+ l4 = eina_list_append(NULL, &data[9]);
+ l4 = eina_list_append(l4, &data[10]);
+ l4 = eina_list_append(l4, &data[11]);
+
+ l5 = eina_list_append(NULL, &data[12]);
+ l5 = eina_list_append(l5, &data[13]);
+ l5 = eina_list_append(l5, &data[14]);
+
+ l1 = eina_list_sort(l1, -1, eina_int_cmp);
+ l3 = eina_list_sort(l3, -1, eina_int_cmp);
+ l4 = eina_list_sort(l4, -1, eina_int_cmp);
+ l5 = eina_list_sort(l5, -1, eina_int_cmp);
+
+ l1 = eina_list_sorted_merge(l1, l3, eina_int_cmp);
+ fail_if(l1 == NULL);
+ fail_if(eina_list_count(l1) != 9);
+
+ l1 = eina_list_sorted_merge(l1, l4, eina_int_cmp);
+ fail_if(l1 == NULL);
+ fail_if(eina_list_count(l1) != 12);
+
+ l1 = eina_list_sorted_merge(l1, l5, eina_int_cmp);
+ fail_if(l1 == NULL);
+ fail_if(eina_list_count(l1) != 15);
+
+ fail_if(!eina_list_sorted_check(l1));
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_sorted_insert)
+{
+ const int data[] = {6, 9, 42, 1, 7, 9, 81, 1664, 1337, 3, 21, 10, 0, 5, 2008};
+ const int data2[] = {5, 0, 3, 2, 1, 0, 1, 2, 3, 4, 5};
+ int i, count;
+ Eina_List *l1, *l2, *itr;
+ void *d;
+
+ eina_init();
+
+ count = sizeof(data) / sizeof(data[0]);
+
+ l1 = NULL;
+ for (i = 0; i < count; i++)
+ l1 = eina_list_sorted_insert(l1, eina_int_cmp, data + i);
+
+ fail_if(l1 == NULL);
+ fail_if(!eina_list_sorted_check(l1));
+
+ l2 = NULL;
+ EINA_LIST_FOREACH(l1, itr, d)
+ l2 = eina_list_sorted_insert(l2, eina_int_cmp, d);
+
+ fail_if(l2 == NULL);
+ fail_if(!eina_list_sorted_check(l2));
+ eina_list_free(l2);
+
+ l2 = NULL;
+ EINA_LIST_REVERSE_FOREACH(l1, itr, d)
+ l2 = eina_list_sorted_insert(l2, eina_int_cmp, d);
+
+ fail_if(l2 == NULL);
+ fail_if(!eina_list_sorted_check(l2));
+ eina_list_free(l2);
+ eina_list_free(l1);
+
+ count = sizeof(data2) / sizeof(data2[0]);
+ l1 = NULL;
+ for (i = 0; i < count; i++)
+ l1 = eina_list_sorted_insert(l1, eina_int_cmp, data2 + i);
+
+ fail_if(l1 == NULL);
+ fail_if(!eina_list_sorted_check(l1));
+ eina_list_free(l1);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_list_split)
+{
+ Eina_List *left = NULL, *right = NULL ;
+ Eina_List *list = NULL;
+ unsigned int i;
+
+ eina_init();
+
+ list = eina_list_append(list, "tigh");
+ list = eina_list_append(list, "adar");
+ list = eina_list_append(list, "baltar");
+ list = eina_list_append(list, "roslin");
+ list = eina_list_append(list, "baltar");
+ list = eina_list_append(list, "roslin");
+ list = eina_list_append(list, "baltar");
+ list = eina_list_append(list, "roslin");
+
+ fail_if(list == NULL);
+ fail_if(eina_list_count(list) != 8);
+
+ for ( i = 0; i < 200; i++)
+ {
+ left = eina_list_split_list(list, eina_list_nth_list(list, i % 2), &right);
+
+ if (i % 2 == 0)
+ fail_if(eina_list_count(left) == 1 && eina_list_count(right) + eina_list_count(left) == i + 7);
+ else
+ fail_if(eina_list_count(left) == 2 && eina_list_count(right) + eina_list_count(left) == i + 7);
+
+ list = eina_list_merge(left, right);
+ list = eina_list_append(list, "roslin");
+ }
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_list(TCase *tc)
+{
+ tcase_add_test(tc, eina_test_simple);
+ tcase_add_test(tc, eina_test_merge);
+ tcase_add_test(tc, eina_test_sorted_insert);
+ tcase_add_test(tc, eina_test_list_split);
+}
diff --git a/src/tests/eina/eina_test_log.c b/src/tests/eina/eina_test_log.c
new file mode 100644
index 000000000..e0f0363b9
--- /dev/null
+++ b/src/tests/eina/eina_test_log.c
@@ -0,0 +1,424 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+struct log_ctx {
+ int level;
+ int line;
+ const char *msg;
+ const char *fnc;
+ const char *dom;
+ Eina_Bool did;
+};
+
+/* tests should not output on success, just uncomment this for debugging */
+//#define SHOW_LOG 1
+
+static void
+_eina_test_log(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ ck_assert_int_eq(ctx->level, level);
+ ck_assert_int_eq(ctx->line, line);
+ ck_assert_str_eq(ctx->msg, fmt);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ck_assert_str_eq(file, __FILE__);
+ ctx->did = EINA_TRUE;
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+#endif
+}
+
+static void
+_eina_test_log_domain(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ ck_assert_int_eq(ctx->level, level);
+ ck_assert_int_eq(ctx->line, line);
+ ck_assert_str_eq(ctx->msg, fmt);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ck_assert_str_eq(file, __FILE__);
+ ck_assert_str_eq(ctx->dom, d->name);
+ ctx->did = EINA_TRUE;
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#endif
+}
+
+static void
+_eina_test_log_safety(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ va_list cp_args;
+ const char *str;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+
+ ck_assert_int_eq(ctx->level, level);
+ ck_assert_str_eq(fmt, "%s");
+ ck_assert_str_eq(ctx->msg, str);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+
+START_TEST(eina_log_macro)
+{
+ struct log_ctx ctx;
+ int oldlevel;
+
+ fail_if(!eina_init());
+
+ oldlevel = eina_log_level_get();
+ eina_log_level_set(EINA_LOG_LEVEL_DBG);
+ eina_log_print_cb_set(_eina_test_log, &ctx);
+
+#define TEST_LOG_CTX(lvl, _msg) \
+ ctx.level = lvl; \
+ ctx.line = __LINE__ + 1; \
+ ctx.msg = _msg; \
+ ctx.fnc = __FUNCTION__; \
+ ctx.did = EINA_FALSE
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_CRITICAL, "Critical message");
+ EINA_LOG_CRIT("Critical message");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_ERR, "An error");
+ EINA_LOG_ERR("An error");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_WARN, "A warning");
+ EINA_LOG_WARN("A warning");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_INFO, "An info");
+ EINA_LOG_INFO("An info");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_DBG, "A debug");
+ EINA_LOG_DBG("A debug");
+ fail_unless(ctx.did);
+
+#undef TEST_LOG_CTX
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+ eina_log_level_set(oldlevel);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_log_domains_macros)
+{
+ struct log_ctx ctx;
+ int oldlevel;
+
+ fail_if(!eina_init());
+
+ /* make global log level blocker */
+ oldlevel = eina_log_level_get();
+ eina_log_level_set(EINA_LOG_LEVEL_CRITICAL);
+ eina_log_print_cb_set(_eina_test_log_domain, &ctx);
+
+ int d = eina_log_domain_register("MyDomain", EINA_COLOR_GREEN);
+ fail_if(d < 0);
+
+ /* make specific domain permissive */
+ eina_log_domain_level_set("MyDomain", EINA_LOG_LEVEL_DBG);
+
+#define TEST_LOG_CTX(lvl, _msg) \
+ ctx.level = lvl; \
+ ctx.line = __LINE__ + 1; \
+ ctx.msg = _msg; \
+ ctx.fnc = __FUNCTION__; \
+ ctx.dom = "MyDomain"; \
+ ctx.did = EINA_FALSE
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_CRITICAL, "A critical message");
+ EINA_LOG_DOM_CRIT(d, "A critical message");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_ERR, "An error");
+ EINA_LOG_DOM_ERR(d, "An error");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_WARN, "A warning");
+ EINA_LOG_DOM_WARN(d, "A warning");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_INFO, "An info");
+ EINA_LOG_DOM_INFO(d, "An info");
+ fail_unless(ctx.did);
+
+ TEST_LOG_CTX(EINA_LOG_LEVEL_DBG, "A debug");
+ EINA_LOG_DOM_DBG(d, "A debug");
+ fail_unless(ctx.did);
+
+#undef TEST_LOG_CTX
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+ eina_log_level_set(oldlevel);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_log_domains_registry)
+{
+ fail_if(!eina_init());
+
+ int i;
+ int d[50];
+
+ for (i = 0; i < 50; i++)
+ {
+ d[i] = eina_log_domain_register("Test", EINA_COLOR_GREEN);
+ fail_if(d[i] < 0);
+ }
+
+ for (i = 0; i < 50; i++)
+ eina_log_domain_unregister(d[i]);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_log_domains_slot_reuse)
+{
+ fail_if(!eina_init());
+ fail_if(!eina_threads_init());
+
+ // Create 9 domains
+ int idx[9];
+ int i;
+
+ for (i = 0; i < 9; i++)
+ {
+ idx[i] = eina_log_domain_register("Test1", EINA_COLOR_GREEN);
+ fail_if(idx[i] < 0);
+ }
+
+ // Slot 0 by default contains the global logger. The above code created
+ // domains for slots indexes from 1 to 9.
+ //
+ // The global logger allocated the first 8 initial slots. The 8th domain
+ // registered on the for loop will create 8 more slots.
+ //
+ // Test will just unregister a domain between 1 and 9 and assure that a new
+ // domain register will be placed on the available slot and not at the end.
+
+ int removed = idx[5];
+ eina_log_domain_unregister(removed);
+
+ int new = eina_log_domain_register("Test Slot", EINA_COLOR_GREEN);
+
+ // Check for slot reuse
+ fail_if(new != removed);
+
+ eina_threads_shutdown();
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_log_level_indexes)
+{
+ struct log_ctx ctx;
+
+ fail_if(!eina_init());
+ fail_if(!eina_threads_init());
+ fail_if(!eina_threads_init());
+
+ int d = eina_log_domain_register("Levels", EINA_COLOR_GREEN);
+ fail_if(d < 0);
+
+ eina_log_print_cb_set(_eina_test_log_domain, &ctx);
+
+#define TEST_LOG_CTX(lvl, _msg) \
+ ctx.level = lvl; \
+ ctx.line = __LINE__ + 1; \
+ ctx.msg = _msg; \
+ ctx.fnc = __FUNCTION__; \
+ ctx.dom = "Levels"; \
+ ctx.did = EINA_FALSE;
+
+ // Displayed unless user sets level lower than -1
+ eina_log_domain_level_set("Levels", -1);
+ TEST_LOG_CTX(-1, "Negative index message");
+ EINA_LOG(d, -1, "Negative index message");
+ fail_unless(ctx.did);
+
+ eina_log_domain_level_set("Levels", -2);
+ TEST_LOG_CTX(-1, "Negative index message");
+ EINA_LOG(d, -1, "Negative index message");
+ fail_if(ctx.did);
+
+ // Displayed only if user sets level 6 or higher
+ eina_log_domain_level_set("Levels", 6);
+ TEST_LOG_CTX(6, "Higher level debug");
+ EINA_LOG(d, 6, "Higher level debug");
+ fail_unless(ctx.did);
+
+ eina_log_domain_level_set("Levels", 5);
+ TEST_LOG_CTX(6, "Higher level debug");
+ EINA_LOG(d, 6, "Higher level debug");
+ fail_if(ctx.did);
+
+#undef TEST_LOG_CTX
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+
+ eina_threads_shutdown();
+ eina_threads_shutdown();
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_log_customize)
+{
+ struct log_ctx ctx;
+ int d;
+
+ /* please don't define EINA_LOG_LEVELS for it */
+#define TEST_DOM "_Test_Log_Dom"
+
+ fail_if(!eina_init());
+
+#define test_set_get(func, val) \
+ eina_log_ ## func ## _set(val); \
+ fail_if(eina_log_ ## func ## _get() != val)
+
+ test_set_get(level, -1234);
+ test_set_get(level, 4567);
+
+#define test_set_get_bool(func) \
+ test_set_get(func, EINA_FALSE); \
+ test_set_get(func, EINA_TRUE)
+
+ test_set_get_bool(color_disable);
+ test_set_get_bool(file_disable);
+ test_set_get_bool(function_disable);
+ test_set_get_bool(abort_on_critical);
+
+ test_set_get(abort_on_critical_level, -1234);
+ test_set_get(abort_on_critical_level, 4567);
+
+ fail_if(eina_log_domain_level_get(TEST_DOM) != eina_log_level_get());
+
+ eina_log_domain_level_set(TEST_DOM, -123);
+ fail_if(eina_log_domain_level_get(TEST_DOM) != -123);
+
+ eina_log_domain_level_set(TEST_DOM, 890);
+ fail_if(eina_log_domain_level_get(TEST_DOM) != 890);
+
+ d = eina_log_domain_register(TEST_DOM, EINA_COLOR_GREEN);
+ fail_if(d < 0);
+
+ fail_if(eina_log_domain_level_get(TEST_DOM) != 890);
+ fail_if(eina_log_domain_registered_level_get(d) != 890);
+
+ eina_log_domain_unregister(d);
+
+#ifdef EINA_SAFETY_CHECKS
+#ifdef SHOW_LOG
+ fputs("NOTE: You should see a failed safety check or "
+ "a crash if compiled without safety checks support.\n",
+ stderr);
+#endif
+ eina_log_abort_on_critical_set(EINA_FALSE);
+ eina_log_function_disable_set(EINA_FALSE);
+
+ eina_log_print_cb_set(_eina_test_log_safety, &ctx);
+ ctx.level = EINA_LOG_LEVEL_ERR;
+ ctx.msg = "safety check failed: _log_domains[domain].deleted is true";
+ ctx.fnc = "eina_log_domain_registered_level_get";
+ ctx.did = EINA_FALSE;
+ fail_if(eina_log_domain_registered_level_get(d) != EINA_LOG_LEVEL_UNKNOWN);
+ fail_unless(ctx.did);
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+#else
+#warning "Compiled without safety checks"
+#endif
+
+#undef test_set_get_bool
+#undef test_set_get
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_log_level_name)
+{
+ char name[4];
+
+ fail_if(!eina_init());
+
+#define tst(level, str) \
+ eina_log_level_name_get(level, name); \
+ fail_if(strcmp(name, str) != 0)
+
+ tst(0, "CRI");
+ tst(1, "ERR");
+ tst(2, "WRN");
+ tst(3, "INF");
+ tst(4, "DBG");
+ tst(5, "005");
+ tst(12, "012");
+ tst(369, "369");
+ tst(-1, "-01");
+ tst(-48, "-48");
+
+#undef tst
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_log(TCase *tc)
+{
+ tcase_add_test(tc, eina_log_macro);
+ tcase_add_test(tc, eina_log_domains_macros);
+ tcase_add_test(tc, eina_log_domains_registry);
+ tcase_add_test(tc, eina_log_domains_slot_reuse);
+ tcase_add_test(tc, eina_log_level_indexes);
+ tcase_add_test(tc, eina_log_customize);
+ tcase_add_test(tc, eina_log_level_name);
+}
diff --git a/src/tests/eina/eina_test_magic.c b/src/tests/eina/eina_test_magic.c
new file mode 100644
index 000000000..d0a374e77
--- /dev/null
+++ b/src/tests/eina/eina_test_magic.c
@@ -0,0 +1,206 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define EINA_MAGIC_DEBUG
+
+#include "eina_suite.h"
+#include "Eina.h"
+#include "eina_safety_checks.h"
+
+#define EINA_MAGIC_TEST 0x7781fee7
+#define EINA_MAGIC_TEST2 0x42241664
+#define EINA_MAGIC_STRING "Eina Magic Test"
+
+typedef struct _Eina_Magic_Struct Eina_Magic_Struct;
+struct _Eina_Magic_Struct
+{
+ EINA_MAGIC
+};
+
+struct log_ctx {
+ const char *msg;
+ const char *fnc;
+ Eina_Bool did;
+};
+
+/* tests should not output on success, just uncomment this for debugging */
+//#define SHOW_LOG 1
+
+static void
+_eina_test_safety_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ va_list cp_args;
+ const char *str;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+
+ ck_assert_int_eq(level, EINA_LOG_LEVEL_ERR);
+ ck_assert_str_eq(fmt, "%s");
+ ck_assert_str_eq(ctx->msg, str);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+
+static void
+_eina_test_magic_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+
+ ck_assert_int_eq(level, EINA_LOG_LEVEL_CRITICAL);
+ ck_assert_str_eq(ctx->msg, fmt);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+
+#ifdef EINA_SAFETY_CHECKS
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+#endif
+
+START_TEST(eina_magic_simple)
+{
+ Eina_Magic_Struct *ems = NULL;
+ struct log_ctx ctx;
+
+ eina_init();
+
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+ eina_magic_string_set(EINA_MAGIC_TEST, EINA_MAGIC_STRING);
+
+#ifdef EINA_SAFETY_CHECKS
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_magic_string_set",
+ "safety check failed: magic_name == NULL");
+ eina_magic_string_set(EINA_MAGIC_TEST2, NULL);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+ fail_unless(ctx.did);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_magic_string_set",
+ "safety check failed: magic_name == NULL");
+ eina_magic_string_set(EINA_MAGIC_TEST2, NULL);
+ fail_unless(ctx.did);
+ fail_if(eina_error_get() != EINA_ERROR_SAFETY_FAILED);
+#endif
+
+ eina_magic_string_set(EINA_MAGIC_TEST2, EINA_MAGIC_STRING);
+
+ fail_if(eina_magic_string_get(EINA_MAGIC_TEST) == NULL);
+ fail_if(strcmp(eina_magic_string_get(
+ EINA_MAGIC_TEST), EINA_MAGIC_STRING) != 0);
+
+ eina_log_print_cb_set(_eina_test_magic_print_cb, &ctx);
+
+#ifdef EINA_MAGIC_DEBUG
+ fail_if(EINA_MAGIC_CHECK(ems, EINA_MAGIC_TEST));
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should see 'Input handle pointer is NULL' below\n");
+#endif
+ TEST_MAGIC_SAFETY(__FUNCTION__,
+ "*** Eina Magic Check Failed !!!\n"
+ " Input handle pointer is NULL !\n"
+ "*** NAUGHTY PROGRAMMER!!!\n"
+ "*** SPANK SPANK SPANK!!!\n"
+ "*** Now go fix your code. Tut tut tut!\n"
+ "\n");
+ EINA_MAGIC_FAIL(ems, EINA_MAGIC_TEST);
+ fail_unless(ctx.did);
+
+ ems = malloc(sizeof (Eina_Magic_Struct));
+ fail_if(!ems);
+ EINA_MAGIC_SET(ems, EINA_MAGIC_TEST);
+
+ fail_if(!EINA_MAGIC_CHECK(ems, EINA_MAGIC_TEST));
+
+ EINA_MAGIC_SET(ems, EINA_MAGIC_NONE);
+#ifdef SHOW_LOG
+ fprintf(stderr,
+ "you should see 'Input handle has already been freed' below\n");
+#endif
+ TEST_MAGIC_SAFETY(__FUNCTION__,
+ "*** Eina Magic Check Failed !!!\n"
+ " Input handle has already been freed!\n"
+ "*** NAUGHTY PROGRAMMER!!!\n"
+ "*** SPANK SPANK SPANK!!!\n"
+ "*** Now go fix your code. Tut tut tut!\n"
+ "\n");
+ EINA_MAGIC_FAIL(ems, EINA_MAGIC_TEST);
+ fail_unless(ctx.did);
+
+ EINA_MAGIC_SET(ems, 42424242);
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should see 'Input handle is wrong type' below\n");
+#endif
+ TEST_MAGIC_SAFETY(__FUNCTION__,
+ "*** Eina Magic Check Failed !!!\n"
+ " Input handle is wrong type\n"
+ " Expected: %08x - %s\n"
+ " Supplied: %08x - %s\n"
+ "*** NAUGHTY PROGRAMMER!!!\n"
+ "*** SPANK SPANK SPANK!!!\n"
+ "*** Now go fix your code. Tut tut tut!\n"
+ "\n");
+ EINA_MAGIC_FAIL(ems, EINA_MAGIC_TEST);
+ fail_unless(ctx.did);
+#endif
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+
+ eina_shutdown();
+}
+END_TEST
+
+void eina_test_magic(TCase *tc)
+{
+ tcase_add_test(tc, eina_magic_simple);
+}
+
diff --git a/src/tests/eina/eina_test_main.c b/src/tests/eina/eina_test_main.c
new file mode 100644
index 000000000..04364a15a
--- /dev/null
+++ b/src/tests/eina/eina_test_main.c
@@ -0,0 +1,62 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+ START_TEST(eina_simple)
+{
+ fail_if(eina_init() != 2); /* one init by test suite */
+ fail_if(eina_shutdown() != 1);
+}
+END_TEST
+
+START_TEST(eina_cpu)
+{
+ fail_if(eina_init() != 2); /* one init by test suite */
+
+ fail_if(eina_cpu_count() <= 0);
+
+ eina_cpu_features_get();
+
+ fail_if(eina_shutdown() != 1);
+}
+END_TEST
+
+START_TEST(eina_hamster)
+{
+ fail_if(eina_init() != 2); /* one init by test suite */
+
+ fail_if(eina_hamster_count() <= 0);
+
+ fail_if(eina_shutdown() != 1);
+}
+END_TEST
+
+void eina_test_main(TCase *tc)
+{
+ tcase_add_test(tc, eina_simple);
+ tcase_add_test(tc, eina_cpu);
+ tcase_add_test(tc, eina_hamster);
+}
diff --git a/src/tests/eina/eina_test_matrixsparse.c b/src/tests/eina/eina_test_matrixsparse.c
new file mode 100644
index 000000000..e07b1eead
--- /dev/null
+++ b/src/tests/eina/eina_test_matrixsparse.c
@@ -0,0 +1,489 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+#define MAX_ROWS 10
+#define MAX_COLS 10
+
+static void eina_matrixsparse_free_cell_cb(void *user_data __UNUSED__,
+ void *cell_data __UNUSED__)
+{
+}
+
+static void matrixsparse_initialize(Eina_Matrixsparse *matrix,
+ long data[MAX_ROWS][MAX_COLS],
+ unsigned long nrows,
+ unsigned long ncols)
+{
+ unsigned long i, j;
+ Eina_Bool r;
+
+ for (i = 0; i < nrows; i++)
+ for (j = 0; j < ncols; j++)
+ if (data[i][j] != 0)
+ {
+ r = eina_matrixsparse_data_idx_set(matrix, i, j, &data[i][j]);
+ fail_if(r == EINA_FALSE);
+ }
+
+}
+
+static void matrixsparse_check(Eina_Matrixsparse *matrix,
+ long data[MAX_ROWS][MAX_COLS],
+ unsigned long nrows __UNUSED__,
+ unsigned long ncols __UNUSED__)
+{
+ unsigned long i, j;
+ long *test1;
+
+ for (i = 0; i < MAX_ROWS; i++)
+ for (j = 0; j < MAX_COLS; j++)
+ {
+ if (data[i][j] != 0)
+ {
+ test1 = eina_matrixsparse_data_idx_get(matrix, i, j);
+ fail_if(test1 == NULL || *test1 != data[i][j]);
+ }
+ else
+ {
+ test1 = eina_matrixsparse_data_idx_get(matrix, i, j);
+ fail_if(test1 != NULL);
+ }
+ }
+}
+
+START_TEST(eina_test_simple)
+{
+ Eina_Matrixsparse *matrix = NULL;
+ Eina_Matrixsparse_Cell *cell = NULL;
+ Eina_Bool r;
+ long *test1, value, value2, value3, value4;
+ unsigned long i, j;
+ unsigned long row, col;
+
+ long data[MAX_ROWS][MAX_COLS];
+
+ for (i = 0; i < MAX_ROWS; i++)
+ for (j = 0; j < MAX_COLS; j++)
+ data[i][j] = 0;
+
+ data[0][3] = 3;
+ data[1][3] = 13;
+ data[1][6] = 16;
+ data[1][9] = 19;
+ data[1][8] = 18;
+ data[1][7] = 17;
+ data[2][8] = 28;
+ data[2][7] = 27;
+ data[2][6] = 26;
+ data[3][5] = 35;
+ data[3][6] = 36;
+ data[3][7] = 37;
+ data[3][9] = 39;
+ data[3][0] = 30;
+ data[4][6] = 46;
+ data[4][8] = 48;
+ data[4][2] = 42;
+ data[4][3] = 43;
+ data[4][7] = 47;
+ data[5][3] = 53;
+ data[6][3] = 63;
+ data[6][4] = 64;
+ data[6][6] = 66;
+ data[7][3] = 73;
+ data[7][7] = 77;
+ data[8][8] = 88;
+
+ value = -1;
+ value2 = -2;
+ value3 = -3;
+ value4 = -4;
+
+ eina_init();
+
+ matrix = eina_matrixsparse_new(MAX_ROWS, MAX_COLS,
+ eina_matrixsparse_free_cell_cb, data);
+ fail_if(matrix == NULL);
+
+ r = eina_matrixsparse_cell_idx_get(matrix, 3, 5, &cell);
+ fail_if(r == EINA_FALSE);
+ fail_if(cell != NULL);
+
+ matrixsparse_initialize(matrix, data, MAX_ROWS, MAX_COLS);
+
+ /* data fetching */
+ test1 = eina_matrixsparse_data_idx_get(matrix, 3, 0);
+ fail_if(test1 == NULL);
+ fail_if(*test1 != data[3][0]);
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 3, 5);
+ fail_if(test1 == NULL);
+ fail_if(*test1 != data[3][5]);
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 3, 6);
+ fail_if(test1 == NULL);
+ fail_if(*test1 != data[3][6]);
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 3, 1);
+ fail_if(test1 != NULL);
+
+ r = eina_matrixsparse_cell_idx_get(matrix, 3, 5, &cell);
+ fail_if(r == EINA_FALSE);
+ fail_if(cell == NULL);
+
+ test1 = eina_matrixsparse_cell_data_get(cell);
+ fail_if(test1 == NULL);
+ fail_if(*test1 != data[3][5]);
+
+ r = eina_matrixsparse_cell_position_get(cell, &row, &col);
+ fail_if(r == EINA_FALSE);
+ fail_if(row != 3 || col != 5);
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 4, 3);
+ fail_if(*test1 != data[4][3]);
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 1, 3);
+ fail_if(*test1 != data[1][3]);
+
+ /* data changing */
+ r = eina_matrixsparse_data_idx_set(matrix, 1, 9, &data[1][9]);
+ fail_if(r == EINA_FALSE);
+
+ r = eina_matrixsparse_data_idx_replace(matrix, 4, 3, &value, (void **)&test1);
+ fail_if(r == EINA_FALSE);
+ fail_if(test1 == NULL);
+ fail_if(*test1 != data[4][3]);
+ data[4][3] = value;
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 4, 3);
+ fail_if(test1 == NULL || *test1 != value);
+
+ r = eina_matrixsparse_cell_data_replace(cell, &value2, (void **)&test1);
+ fail_if(r == EINA_FALSE);
+ fail_if(test1 == NULL);
+ fail_if(*test1 != data[3][5]);
+ data[3][5] = value2;
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 3, 5);
+ fail_if(test1 == NULL);
+ fail_if(*test1 != value2);
+
+ r = eina_matrixsparse_cell_idx_get(matrix, 4, 2, &cell);
+ fail_if(r == EINA_FALSE || cell == NULL);
+
+ r = eina_matrixsparse_cell_data_set(cell, &value3);
+ fail_if(r == EINA_FALSE);
+ data[4][2] = value3;
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 4, 2);
+ fail_if(test1 == NULL || *test1 != value3);
+
+ r = eina_matrixsparse_data_idx_replace(matrix,
+ 6,
+ 5,
+ &value4,
+ (void **)&test1);
+ fail_if(r == EINA_FALSE || test1 != NULL);
+ data[6][5] = value4;
+
+
+ /* cell deletion */
+ r = eina_matrixsparse_row_idx_clear(matrix, 4);
+ fail_if(r == EINA_FALSE);
+ data[4][6] = 0;
+ data[4][8] = 0;
+ data[4][2] = 0;
+ data[4][3] = 0;
+ data[4][7] = 0;
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 4, 3);
+ fail_if(test1 != NULL);
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 4, 8);
+ fail_if(test1 != NULL);
+
+ test1 = eina_matrixsparse_data_idx_get(matrix, 5, 3);
+ fail_if(*test1 != data[5][3]);
+
+ r = eina_matrixsparse_column_idx_clear(matrix, 3);
+ fail_if(r != EINA_TRUE);
+ data[0][3] = 0;
+ data[1][3] = 0;
+ data[4][3] = 0;
+ data[5][3] = 0;
+ data[6][3] = 0;
+ data[7][3] = 0;
+
+ r = eina_matrixsparse_cell_idx_clear(matrix, 3, 5);
+ fail_if(r != EINA_TRUE);
+ data[3][5] = 0;
+
+ r = eina_matrixsparse_cell_idx_clear(matrix, 3, 9);
+ fail_if(r != EINA_TRUE);
+ data[3][9] = 0;
+
+ r = eina_matrixsparse_cell_idx_clear(matrix, 4, 3);
+ fail_if(r != EINA_TRUE);
+ data[4][3] = 0;
+
+ r = eina_matrixsparse_cell_idx_get(matrix, 3, 7, &cell);
+ fail_if(r == EINA_FALSE);
+ fail_if(cell == NULL);
+
+ r = eina_matrixsparse_cell_clear(cell);
+ fail_if(r == EINA_FALSE);
+ data[3][7] = 0;
+
+ r = eina_matrixsparse_cell_idx_get(matrix, 2, 7, &cell);
+ fail_if(r == EINA_FALSE);
+
+ r = eina_matrixsparse_cell_idx_clear(matrix, 2, 8);
+ fail_if(r == EINA_FALSE);
+ data[2][8] = 0;
+
+ r = eina_matrixsparse_cell_idx_clear(matrix, 2, 7);
+ fail_if(r == EINA_FALSE);
+ data[2][7] = 0;
+
+ r = eina_matrixsparse_cell_idx_get(matrix, 7, 7, &cell);
+ fail_if(r == EINA_FALSE);
+
+ r = eina_matrixsparse_row_idx_clear(matrix, 8);
+ fail_if(r == EINA_FALSE);
+ data[8][8] = 0;
+
+ r = eina_matrixsparse_row_idx_clear(matrix, 7);
+ fail_if(r == EINA_FALSE);
+ data[7][3] = 0;
+ data[7][7] = 0;
+
+ matrixsparse_check(matrix, data, MAX_ROWS, MAX_COLS);
+ eina_matrixsparse_free(matrix);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_resize)
+{
+ Eina_Matrixsparse *matrix = NULL;
+ Eina_Bool r;
+ unsigned long i, j;
+ unsigned long nrows, ncols;
+
+ long data[MAX_ROWS][MAX_COLS];
+
+ for (i = 0; i < MAX_ROWS; i++)
+ for (j = 0; j < MAX_COLS; j++)
+ data[i][j] = 0;
+
+ eina_init();
+
+ matrix = eina_matrixsparse_new(MAX_ROWS, MAX_COLS,
+ eina_matrixsparse_free_cell_cb, data);
+ fail_if(matrix == NULL);
+
+ /* cell insertion */
+ data[0][5] = 5;
+ data[1][0] = 10;
+ data[1][3] = 13;
+ data[1][6] = 16;
+ data[1][9] = 19;
+ data[1][8] = 18;
+ data[1][7] = 17;
+ data[2][8] = 28;
+ data[2][7] = 27;
+ data[2][6] = 26;
+ data[3][0] = 30;
+ data[3][5] = 35;
+ data[3][6] = 36;
+ data[3][7] = 37;
+ data[3][9] = 39;
+ data[3][0] = 30;
+ data[4][8] = 48;
+ data[4][2] = 42;
+ data[4][3] = 43;
+ data[4][7] = 47;
+ data[4][6] = 46;
+ data[5][3] = 53;
+ data[6][3] = 63;
+ data[6][4] = 64;
+ data[6][6] = 66;
+ data[7][3] = 73;
+ data[7][7] = 77;
+ data[8][8] = 88;
+
+ matrixsparse_initialize(matrix, data, MAX_ROWS, MAX_COLS);
+
+ eina_matrixsparse_size_get(matrix, &nrows, &ncols);
+ fail_if(nrows != MAX_ROWS || ncols != MAX_COLS);
+
+ r = eina_matrixsparse_size_set(matrix, nrows - 2, ncols - 2);
+ fail_if(r == EINA_FALSE);
+ data[1][9] = 0;
+ data[1][8] = 0;
+ data[2][8] = 0;
+ data[3][9] = 0;
+ data[4][8] = 0;
+ data[8][8] = 0;
+ matrixsparse_check(matrix, data, MAX_ROWS, MAX_COLS);
+
+ r = eina_matrixsparse_size_set(matrix, 5, 1);
+ fail_if(r == EINA_FALSE);
+ data[0][5] = 0;
+ data[1][3] = 0;
+ data[1][6] = 0;
+ data[1][7] = 0;
+ data[2][7] = 0;
+ data[2][6] = 0;
+ data[3][5] = 0;
+ data[3][6] = 0;
+ data[3][7] = 0;
+ data[4][2] = 0;
+ data[4][3] = 0;
+ data[4][7] = 0;
+ data[4][6] = 0;
+ data[5][3] = 0;
+ data[6][3] = 0;
+ data[6][4] = 0;
+ data[6][6] = 0;
+ data[7][3] = 0;
+ data[7][7] = 0;
+ matrixsparse_check(matrix, data, MAX_ROWS, MAX_COLS);
+
+ r = eina_matrixsparse_size_set(matrix, 1, 1);
+ fail_if(r == EINA_FALSE);
+ data[3][0] = 0;
+ data[1][0] = 0;
+ matrixsparse_check(matrix, data, MAX_ROWS, MAX_COLS);
+
+ r = eina_matrixsparse_size_set(matrix, 5, 4);
+ fail_if(r == EINA_FALSE);
+
+ r = eina_matrixsparse_data_idx_set(matrix, 4, 2, &data[4][2]);
+ fail_if(r == EINA_FALSE);
+ data[4][2] = 42;
+ matrixsparse_check(matrix, data, MAX_ROWS, MAX_COLS);
+
+ r = eina_matrixsparse_size_set(matrix, 5, 1);
+ fail_if(r == EINA_FALSE);
+ data[4][2] = 0;
+ matrixsparse_check(matrix, data, MAX_ROWS, MAX_COLS);
+
+ eina_matrixsparse_free(matrix);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_iterators)
+{
+ Eina_Matrixsparse *matrix = NULL;
+ Eina_Matrixsparse_Cell *cell = NULL;
+ Eina_Iterator *it = NULL;
+ Eina_Bool r;
+ long *test1, value;
+ unsigned long i, j;
+ unsigned long row, col;
+
+ long data[MAX_ROWS][MAX_COLS];
+
+ value = 0;
+ for (i = 0; i < MAX_ROWS; i++)
+ {
+ for (j = 0; j < MAX_COLS; j++)
+ {
+ data[i][j] = value++;
+ printf("%4ld ", data[i][j]);
+ }
+ printf("\n");
+ }
+
+ eina_init();
+
+ matrix = eina_matrixsparse_new(MAX_ROWS, MAX_COLS,
+ eina_matrixsparse_free_cell_cb, data);
+ fail_if(matrix == NULL);
+
+ r = eina_matrixsparse_data_idx_set(matrix, 3, 5, &data[3][5]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 3, 6, &data[3][6]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 3, 7, &data[3][7]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 3, 9, &data[3][9]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 3, 0, &data[3][0]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 4, 6, &data[4][6]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 4, 8, &data[4][8]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 4, 2, &data[4][2]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 4, 3, &data[4][3]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 4, 7, &data[4][7]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 6, 4, &data[6][4]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 5, 3, &data[5][3]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 6, 3, &data[6][3]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 7, 3, &data[7][3]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 0, 3, &data[0][3]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 1, 3, &data[1][3]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 1, 6, &data[1][6]);
+ fail_if(r == EINA_FALSE);
+ r = eina_matrixsparse_data_idx_set(matrix, 1, 9, &data[1][9]);
+ fail_if(r == EINA_FALSE);
+
+ it = eina_matrixsparse_iterator_new(matrix);
+ fail_if(it == NULL);
+ EINA_ITERATOR_FOREACH(it, cell)
+ {
+ fail_if(cell == NULL);
+ r = eina_matrixsparse_cell_position_get(cell, &row, &col);
+ fail_if(r == EINA_FALSE);
+
+ test1 = eina_matrixsparse_cell_data_get(cell);
+ fail_if(test1 == NULL || *test1 != data[row][col]);
+ }
+ eina_iterator_free(it);
+
+ it = eina_matrixsparse_iterator_complete_new(matrix);
+ fail_if(it == NULL);
+ EINA_ITERATOR_FOREACH(it, cell)
+ {
+ fail_if(cell == NULL);
+ r = eina_matrixsparse_cell_position_get(cell, &row, &col);
+ fail_if(r == EINA_FALSE);
+
+ test1 = eina_matrixsparse_cell_data_get(cell);
+ if (test1)
+ fail_if(*test1 != data[row][col]);
+ }
+ eina_iterator_free(it);
+
+ eina_matrixsparse_free(matrix);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_matrixsparse(TCase *tc)
+{
+ tcase_add_test(tc, eina_test_simple);
+ tcase_add_test(tc, eina_test_resize);
+ tcase_add_test(tc, eina_test_iterators);
+}
diff --git a/src/tests/eina/eina_test_mempool.c b/src/tests/eina/eina_test_mempool.c
new file mode 100644
index 000000000..7106afa94
--- /dev/null
+++ b/src/tests/eina/eina_test_mempool.c
@@ -0,0 +1,187 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static Eina_Array *_modules;
+
+static void
+_mempool_init(void)
+{
+ eina_init();
+ /* force modules to be loaded in case they are not installed */
+ _modules = eina_module_list_get(NULL,
+ PACKAGE_BUILD_DIR "/src/modules",
+ EINA_TRUE,
+ NULL,
+ NULL);
+ eina_module_list_load(_modules);
+}
+
+static void
+_mempool_shutdown(void)
+{
+ eina_module_list_free(_modules);
+ /* TODO delete the list */
+ eina_shutdown();
+}
+
+static void
+_eina_mempool_test(Eina_Mempool *mp, Eina_Bool with_realloc, Eina_Bool with_gc)
+{
+ int *tbl[512];
+ int i;
+
+ fail_if(!mp);
+
+ for (i = 0; i < 512; ++i)
+ {
+ tbl[i] = eina_mempool_malloc(mp, sizeof (int));
+ fail_if(!tbl[i]);
+ *tbl[i] = i;
+ }
+
+ for (i = 0; i < 512; ++i)
+ fail_if(*tbl[i] != i);
+
+ for (i = 0; i < 256; ++i)
+ eina_mempool_free(mp, tbl[i]);
+
+ if (with_realloc)
+ fail_if(eina_mempool_realloc(mp, tbl[500], 25) == NULL);
+ else
+ fail_if(eina_mempool_realloc(mp, tbl[500], 25) != NULL);
+
+ if (with_gc)
+ {
+ eina_mempool_gc(mp);
+ eina_mempool_statistics(mp);
+ }
+
+ eina_mempool_del(mp);
+}
+
+#ifdef EINA_BUILD_CHAINED_POOL
+START_TEST(eina_mempool_chained_mempool)
+{
+ Eina_Mempool *mp;
+
+ _mempool_init();
+
+ mp = eina_mempool_add("chained_mempool", "test", NULL, sizeof (int), 256);
+ _eina_mempool_test(mp, EINA_FALSE, EINA_FALSE);
+
+ _mempool_shutdown();
+}
+END_TEST
+#endif
+
+#ifdef EINA_BUILD_PASS_THROUGH
+START_TEST(eina_mempool_pass_through)
+{
+ Eina_Mempool *mp;
+
+ _mempool_init();
+
+ mp = eina_mempool_add("pass_through", "test", NULL, sizeof (int), 8, 0);
+ _eina_mempool_test(mp, EINA_TRUE, EINA_FALSE);
+
+ _mempool_shutdown();
+}
+END_TEST
+#endif
+
+#ifdef EINA_BUILD_FIXED_BITMAP
+START_TEST(eina_mempool_fixed_bitmap)
+{
+ Eina_Mempool *mp;
+
+ _mempool_init();
+
+ mp = eina_mempool_add("fixed_bitmap", "test", NULL, sizeof (int));
+ _eina_mempool_test(mp, EINA_FALSE, EINA_FALSE);
+
+ _mempool_shutdown();
+}
+END_TEST
+#endif
+
+#ifdef EINA_BUILD_EMEMOA_FIXED
+START_TEST(eina_mempool_ememoa_fixed)
+{
+ Eina_Mempool *mp;
+
+ _mempool_init();
+
+ mp = eina_mempool_add("ememoa_fixed", "test", NULL, sizeof (int), 8, 0);
+ _eina_mempool_test(mp, EINA_FALSE, EINA_TRUE);
+
+ _mempool_shutdown();
+}
+END_TEST
+#endif
+
+#ifdef EINA_BUILD_EMEMOA_UNKNOWN
+START_TEST(eina_mempool_ememoa_unknown)
+{
+ Eina_Mempool *mp;
+
+ _mempool_init();
+
+ mp = eina_mempool_add("ememoa_unknown",
+ "test",
+ NULL,
+ 0,
+ 2,
+ sizeof (int),
+ 8,
+ sizeof (int) * 2,
+ 8);
+ _eina_mempool_test(mp, EINA_TRUE, EINA_TRUE);
+
+ _mempool_shutdown();
+}
+END_TEST
+#endif
+
+void
+eina_test_mempool(TCase *tc)
+{
+#ifdef EINA_BUILD_CHAINED_POOL
+ tcase_add_test(tc, eina_mempool_chained_mempool);
+#endif
+#ifdef EINA_BUILD_PASS_THROUGH
+ tcase_add_test(tc, eina_mempool_pass_through);
+#endif
+#ifdef EINA_BUILD_FIXED_BITMAP
+ tcase_add_test(tc, eina_mempool_fixed_bitmap);
+#endif
+#ifdef EINA_BUILD_EMEMOA_FIXED
+ tcase_add_test(tc, eina_mempool_ememoa_fixed);
+#endif
+#ifdef EINA_BUILD_EMEMOA_UNKNOWN
+ tcase_add_test(tc, eina_mempool_ememoa_unknown);
+#endif
+}
+
+
diff --git a/src/tests/eina/eina_test_model.c b/src/tests/eina/eina_test_model.c
new file mode 100644
index 000000000..54a22581b
--- /dev/null
+++ b/src/tests/eina/eina_test_model.c
@@ -0,0 +1,1288 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2012 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static void
+_eina_test_model_check_safety_null(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args)
+{
+ Eina_Bool *ck = data;
+
+ if ((level == EINA_LOG_LEVEL_ERR) && (strcmp(fmt, "%s") == 0))
+ {
+ const char *str;
+ va_list cp_args;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+ if (eina_str_has_prefix(str, "safety check failed: ") &&
+ eina_str_has_suffix(str, " == NULL"))
+ {
+ *ck = EINA_TRUE;
+ return;
+ }
+ }
+ *ck = EINA_FALSE;
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+}
+
+static void
+_eina_test_model_check_safety_false(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args)
+{
+ Eina_Bool *ck = data;
+
+ if ((level == EINA_LOG_LEVEL_ERR) && (strcmp(fmt, "%s") == 0))
+ {
+ const char *str;
+ va_list cp_args;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+ if (eina_str_has_prefix(str, "safety check failed: ") &&
+ eina_str_has_suffix(str, " is false"))
+ {
+ *ck = EINA_TRUE;
+ return;
+ }
+ }
+ *ck = EINA_FALSE;
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+}
+
+static void
+_eina_test_model_cb_count(void *data, Eina_Model *model, const Eina_Model_Event_Description *desc, void *event_info)
+{
+ unsigned *count = data;
+ (*count)++;
+#if SHOW_LOG
+ if ((desc->type) && (strcmp(desc->type, "u") == 0))
+ {
+ unsigned *pos = event_info;
+ printf("%2u %p %s at %u\n", *count, model, desc->name, *pos);
+ }
+ else
+ printf("%2u %p %s\n", *count, model, desc->name);
+#else
+ (void)model;
+ (void)desc;
+ (void)event_info;
+#endif
+}
+
+START_TEST(eina_model_test_properties)
+{
+ unsigned int count_del = 0, count_pset = 0, count_pdel = 0;
+ Eina_Model *m;
+ Eina_Value inv, outv;
+ int i;
+ char *s;
+ Eina_List *lst;
+ Eina_Bool ck;
+
+ eina_init();
+
+ m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(m != NULL);
+
+ eina_model_event_callback_add
+ (m, "deleted", _eina_test_model_cb_count, &count_del);
+ eina_model_event_callback_add
+ (m, "property,set", _eina_test_model_cb_count, &count_pset);
+ eina_model_event_callback_add
+ (m, "property,deleted", _eina_test_model_cb_count, &count_pdel);
+
+ fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&inv, 1234));
+ fail_unless(eina_value_get(&inv, &i));
+ ck_assert_int_eq(i, 1234);
+
+ fail_unless(eina_model_property_set(m, "abc", &inv));
+
+ fail_unless(eina_value_set(&inv, 5678));
+ fail_unless(eina_model_property_set(m, "xyz", &inv));
+
+ fail_unless(eina_value_set(&inv, 171));
+ fail_unless(eina_model_property_set(m, "value", &inv));
+
+ lst = eina_model_properties_names_list_get(m);
+ ck_assert_int_eq(eina_list_count(lst), 3);
+
+ lst = eina_list_sort(lst, 0, EINA_COMPARE_CB(strcmp));
+ ck_assert_str_eq("abc", eina_list_nth(lst, 0));
+ ck_assert_str_eq("value", eina_list_nth(lst, 1));
+ ck_assert_str_eq("xyz", eina_list_nth(lst, 2));
+
+ eina_model_properties_names_list_free(lst);
+
+ fail_unless(eina_model_property_get(m, "abc", &outv));
+ fail_unless(eina_value_get(&outv, &i));
+ ck_assert_int_eq(i, 1234);
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "xyz", &outv));
+ fail_unless(eina_value_get(&outv, &i));
+ ck_assert_int_eq(i, 5678);
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "value", &outv));
+ fail_unless(eina_value_get(&outv, &i));
+ ck_assert_int_eq(i, 171);
+ eina_value_flush(&outv);
+
+ fail_unless(eina_value_set(&inv, 666));
+ fail_unless(eina_model_property_set(m, "value", &inv));
+ fail_unless(eina_model_property_get(m, "value", &outv));
+ fail_unless(eina_value_get(&outv, &i));
+ ck_assert_int_eq(i, 666);
+
+ eina_value_flush(&outv);
+ eina_value_flush(&inv);
+
+ fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_STRING));
+ fail_unless(eina_value_set(&inv, "Hello world!"));
+ fail_unless(eina_model_property_set(m, "string", &inv));
+
+ fail_unless(eina_model_property_get(m, "string", &outv));
+ fail_unless(eina_value_get(&outv, &s));
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "Hello world!");
+
+ eina_value_flush(&outv);
+ eina_value_flush(&inv);
+
+ fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_STRINGSHARE));
+ fail_unless(eina_value_set(&inv, "Hello world-STRINGSHARED!"));
+ fail_unless(eina_model_property_set(m, "stringshare", &inv));
+ /* set twice to see if references drop to zero before new add, shouldn't */
+ fail_unless(eina_model_property_set(m, "stringshare", &inv));
+
+ fail_unless(eina_model_property_get(m, "stringshare", &outv));
+ fail_unless(eina_value_get(&outv, &s));
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "Hello world-STRINGSHARED!");
+
+ eina_value_flush(&outv);
+ eina_value_flush(&inv);
+
+ s = eina_model_to_string(m);
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "Eina_Model_Type_Generic({abc: 1234, string: Hello world!, stringshare: Hello world-STRINGSHARED!, value: 666, xyz: 5678}, [])");
+ free(s);
+
+ fail_unless(eina_model_property_del(m, "value"));
+
+ /* negative test (check safety was displayed by using print_cb) */
+ eina_log_print_cb_set(_eina_test_model_check_safety_null, &ck);
+
+ ck = EINA_FALSE;
+ fail_if(eina_model_property_get(m, "non-existent", &outv));
+ fail_unless(ck == EINA_TRUE);
+
+ ck = EINA_FALSE;
+ fail_if(eina_model_property_get(m, NULL, &outv));
+ fail_unless(ck == EINA_TRUE);
+
+ ck = EINA_FALSE;
+ fail_if(eina_model_property_del(m, "value"));
+ fail_unless(ck == EINA_TRUE);
+
+ /* revert print_cb to default */
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+
+ eina_model_unref(m);
+ ck_assert_int_eq(count_del, 1);
+ ck_assert_int_eq(count_pset, 7);
+ ck_assert_int_eq(count_pdel, 1);
+ eina_shutdown();
+}
+END_TEST
+
+static int
+eina_model_test_children_reverse_cmp(const Eina_Model *a, const Eina_Model *b)
+{
+ return - eina_model_compare(a, b);
+}
+
+START_TEST(eina_model_test_children)
+{
+ unsigned int count_del = 0, count_cset = 0, count_cins = 0, count_cdel = 0;
+ Eina_Model *m, *c;
+ char *s;
+ int i;
+
+ eina_init();
+
+ m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(m != NULL);
+
+ eina_model_event_callback_add
+ (m, "deleted", _eina_test_model_cb_count, &count_del);
+ eina_model_event_callback_add
+ (m, "child,set", _eina_test_model_cb_count, &count_cset);
+ eina_model_event_callback_add
+ (m, "child,inserted", _eina_test_model_cb_count, &count_cins);
+ eina_model_event_callback_add
+ (m, "child,deleted", _eina_test_model_cb_count, &count_cdel);
+
+ for (i = 0; i < 10; i++)
+ {
+ Eina_Value val;
+
+ c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(c != NULL);
+
+ eina_model_event_callback_add
+ (c, "deleted", _eina_test_model_cb_count, &count_del);
+ eina_model_event_callback_add
+ (c, "child,set", _eina_test_model_cb_count, &count_cset);
+ eina_model_event_callback_add
+ (c, "child,inserted", _eina_test_model_cb_count, &count_cins);
+ eina_model_event_callback_add
+ (c, "child,deleted", _eina_test_model_cb_count, &count_cdel);
+
+ fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&val, i));
+ fail_unless(eina_model_property_set(c, "value", &val));
+
+ fail_unless(eina_model_child_append(m, c) >= 0);
+ ck_assert_int_eq(eina_model_refcount(c), 2);
+
+ eina_value_flush(&val);
+ eina_model_unref(c);
+ }
+
+ ck_assert_int_eq(eina_model_child_count(m), 10);
+
+ for (i = 0; i < 10; i++)
+ {
+ Eina_Value val;
+ int x;
+
+ c = eina_model_child_get(m, i);
+ fail_unless(c != NULL);
+ ck_assert_int_eq(eina_model_refcount(c), 2);
+
+ fail_unless(eina_model_property_get(c, "value", &val));
+ fail_unless(eina_value_get(&val, &x));
+ ck_assert_int_eq(x, i);
+
+ eina_value_flush(&val);
+ eina_model_unref(c);
+ }
+
+ eina_model_child_sort(m, EINA_COMPARE_CB(eina_model_test_children_reverse_cmp));
+
+ for (i = 0; i < 10; i++)
+ {
+ Eina_Value val;
+ int x;
+
+ c = eina_model_child_get(m, i);
+ fail_unless(c != NULL);
+ ck_assert_int_eq(eina_model_refcount(c), 2);
+
+ fail_unless(eina_model_property_get(c, "value", &val));
+ fail_unless(eina_value_get(&val, &x));
+ ck_assert_int_eq(x, 10 - i - 1);
+
+ eina_value_flush(&val);
+ eina_model_unref(c);
+ }
+
+ eina_model_child_sort(m, EINA_COMPARE_CB(eina_model_compare));
+
+ s = eina_model_to_string(m);
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "Eina_Model_Type_Generic({}, [Eina_Model_Type_Generic({value: 0}, []), Eina_Model_Type_Generic({value: 1}, []), Eina_Model_Type_Generic({value: 2}, []), Eina_Model_Type_Generic({value: 3}, []), Eina_Model_Type_Generic({value: 4}, []), Eina_Model_Type_Generic({value: 5}, []), Eina_Model_Type_Generic({value: 6}, []), Eina_Model_Type_Generic({value: 7}, []), Eina_Model_Type_Generic({value: 8}, []), Eina_Model_Type_Generic({value: 9}, [])])");
+ free(s);
+
+ c = eina_model_child_get(m, 0);
+ eina_model_child_set(m, 1, c);
+ eina_model_unref(c);
+
+ eina_model_child_del(m, 0);
+ eina_model_child_del(m, 8);
+
+ s = eina_model_to_string(m);
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "Eina_Model_Type_Generic({}, [Eina_Model_Type_Generic({value: 0}, []), Eina_Model_Type_Generic({value: 2}, []), Eina_Model_Type_Generic({value: 3}, []), Eina_Model_Type_Generic({value: 4}, []), Eina_Model_Type_Generic({value: 5}, []), Eina_Model_Type_Generic({value: 6}, []), Eina_Model_Type_Generic({value: 7}, []), Eina_Model_Type_Generic({value: 8}, [])])");
+ free(s);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+
+ ck_assert_int_eq(count_del, 11);
+ ck_assert_int_eq(count_cins, 10);
+ ck_assert_int_eq(count_cset, 1);
+ ck_assert_int_eq(count_cdel, 2);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_model_test_copy)
+{
+ unsigned int count_del = 0;
+ Eina_Model *m, *cp;
+ char *s1, *s2;
+ int i;
+
+ eina_init();
+
+ m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(m != NULL);
+
+ eina_model_event_callback_add
+ (m, "deleted", _eina_test_model_cb_count, &count_del);
+
+ for (i = 0; i < 5; i++)
+ {
+ Eina_Value val;
+ char name[2] = {'a'+ i, 0};
+ fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&val, i));
+ fail_unless(eina_model_property_set(m, name, &val));
+ eina_value_flush(&val);
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ Eina_Value val;
+ Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(c != NULL);
+ fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&val, i));
+ fail_unless(eina_model_property_set(c, "x", &val));
+
+ eina_model_event_callback_add
+ (c, "deleted", _eina_test_model_cb_count, &count_del);
+
+ fail_unless(eina_model_child_append(m, c) >= 0);
+ eina_model_unref(c);
+ eina_value_flush(&val);
+ }
+
+ s1 = eina_model_to_string(m);
+ fail_unless(s1 != NULL);
+ ck_assert_str_eq(s1, "Eina_Model_Type_Generic({a: 0, b: 1, c: 2, d: 3, e: 4}, [Eina_Model_Type_Generic({x: 0}, []), Eina_Model_Type_Generic({x: 1}, []), Eina_Model_Type_Generic({x: 2}, []), Eina_Model_Type_Generic({x: 3}, []), Eina_Model_Type_Generic({x: 4}, [])])");
+
+ cp = eina_model_copy(m);
+ fail_unless(cp != NULL);
+ fail_unless(cp != m);
+
+ eina_model_event_callback_add
+ (cp, "deleted", _eina_test_model_cb_count, &count_del);
+
+ s2 = eina_model_to_string(cp);
+ fail_unless(s2 != NULL);
+ ck_assert_str_eq(s1, s2);
+
+ for (i = 0; i < 5; i++)
+ {
+ Eina_Model *c1 = eina_model_child_get(m, i);
+ Eina_Model *c2 = eina_model_child_get(cp, i);
+
+ fail_unless(c1 != NULL);
+ fail_unless(c1 == c2);
+ ck_assert_int_eq(eina_model_refcount(c1), 4);
+
+ eina_model_unref(c1);
+ eina_model_unref(c2);
+ }
+
+ free(s1);
+ free(s2);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+
+ ck_assert_int_eq(eina_model_refcount(cp), 1);
+ eina_model_unref(cp);
+
+ ck_assert_int_eq(count_del, 2 + 5);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_model_test_deep_copy)
+{
+ unsigned int count_del = 0;
+ Eina_Model *m, *cp;
+ char *s1, *s2;
+ int i;
+
+ eina_init();
+
+ m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(m != NULL);
+
+ eina_model_event_callback_add
+ (m, "deleted", _eina_test_model_cb_count, &count_del);
+
+ for (i = 0; i < 5; i++)
+ {
+ Eina_Value val;
+ char name[2] = {'a'+ i, 0};
+ fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&val, i));
+ fail_unless(eina_model_property_set(m, name, &val));
+ eina_value_flush(&val);
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ Eina_Value val;
+ Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(c != NULL);
+ fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&val, i));
+ fail_unless(eina_model_property_set(c, "x", &val));
+
+ eina_model_event_callback_add
+ (c, "deleted", _eina_test_model_cb_count, &count_del);
+
+ fail_unless(eina_model_child_append(m, c) >= 0);
+ eina_model_unref(c);
+ eina_value_flush(&val);
+ }
+
+ s1 = eina_model_to_string(m);
+ fail_unless(s1 != NULL);
+ ck_assert_str_eq(s1, "Eina_Model_Type_Generic({a: 0, b: 1, c: 2, d: 3, e: 4}, [Eina_Model_Type_Generic({x: 0}, []), Eina_Model_Type_Generic({x: 1}, []), Eina_Model_Type_Generic({x: 2}, []), Eina_Model_Type_Generic({x: 3}, []), Eina_Model_Type_Generic({x: 4}, [])])");;
+
+ cp = eina_model_deep_copy(m);
+ fail_unless(cp != NULL);
+ fail_unless(cp != m);
+
+ eina_model_event_callback_add
+ (cp, "deleted", _eina_test_model_cb_count, &count_del);
+
+ s2 = eina_model_to_string(cp);
+ fail_unless(s2 != NULL);
+ ck_assert_str_eq(s1, s2);
+
+ for (i = 0; i < 5; i++)
+ {
+ Eina_Model *c1 = eina_model_child_get(m, i);
+ Eina_Model *c2 = eina_model_child_get(cp, i);
+
+ fail_unless(c1 != NULL);
+ fail_unless(c1 != c2);
+ ck_assert_int_eq(eina_model_refcount(c1), 2);
+ ck_assert_int_eq(eina_model_refcount(c2), 2);
+
+ eina_model_event_callback_add
+ (c2, "deleted", _eina_test_model_cb_count, &count_del);
+
+ eina_model_unref(c1);
+ eina_model_unref(c2);
+ }
+
+ free(s1);
+ free(s2);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+
+ ck_assert_int_eq(eina_model_refcount(cp), 1);
+ eina_model_unref(cp);
+
+ ck_assert_int_eq(count_del, 2 + 10);
+
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Model *
+eina_model_test_iterator_setup(unsigned int *count_del)
+{
+ Eina_Model *m;
+ int i;
+
+ m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(m != NULL);
+
+ eina_model_event_callback_add
+ (m, "deleted", _eina_test_model_cb_count, count_del);
+
+ for (i = 0; i < 5; i++)
+ {
+ Eina_Value val;
+ Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(c != NULL);
+ fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&val, i));
+ fail_unless(eina_model_property_set(c, "x", &val));
+
+ eina_model_event_callback_add
+ (c, "deleted", _eina_test_model_cb_count, count_del);
+
+ fail_unless(eina_model_child_append(m, c) >= 0);
+ eina_model_unref(c);
+ eina_value_flush(&val);
+ }
+
+ return m;
+}
+
+START_TEST(eina_model_test_child_iterator)
+{
+ unsigned int count_del = 0;
+ Eina_Iterator *it;
+ Eina_Model *m, *c;
+ int i = 0;
+
+ eina_init();
+
+ m = eina_model_test_iterator_setup(&count_del);
+
+ it = eina_model_child_iterator_get(m);
+ fail_unless(it != NULL);
+ EINA_ITERATOR_FOREACH(it, c)
+ {
+ Eina_Value tmp;
+ int x;
+
+ ck_assert_int_eq(eina_model_refcount(c), 2);
+ fail_unless(eina_model_property_get(c, "x", &tmp));
+ fail_unless(eina_value_get(&tmp, &x));
+ ck_assert_int_eq(x, i);
+
+ eina_model_unref(c);
+ i++;
+ }
+ ck_assert_int_eq(i, 5);
+ eina_iterator_free(it);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+ ck_assert_int_eq(count_del, 6);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_model_test_child_reversed_iterator)
+{
+ unsigned int count_del = 0;
+ Eina_Iterator *it;
+ Eina_Model *m, *c;
+ int i = 4;
+
+ eina_init();
+
+ m = eina_model_test_iterator_setup(&count_del);
+
+ it = eina_model_child_reversed_iterator_get(m);
+ fail_unless(it != NULL);
+ EINA_ITERATOR_FOREACH(it, c)
+ {
+ Eina_Value tmp;
+ int x;
+
+ ck_assert_int_eq(eina_model_refcount(c), 2);
+ fail_unless(eina_model_property_get(c, "x", &tmp));
+ fail_unless(eina_value_get(&tmp, &x));
+ ck_assert_int_eq(x, i);
+
+ eina_model_unref(c);
+ i--;
+ }
+ ck_assert_int_eq(i, -1);
+ eina_iterator_free(it);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+ ck_assert_int_eq(count_del, 6);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_model_test_child_sorted_iterator)
+{
+ unsigned int count_del = 0;
+ Eina_Iterator *it;
+ Eina_Model *m, *c;
+ int i = 4;
+
+ eina_init();
+
+ m = eina_model_test_iterator_setup(&count_del);
+
+ it = eina_model_child_sorted_iterator_get
+ (m, EINA_COMPARE_CB(eina_model_test_children_reverse_cmp));
+ fail_unless(it != NULL);
+ EINA_ITERATOR_FOREACH(it, c)
+ {
+ Eina_Value tmp;
+ int x;
+
+ /* 3 because sort takes an extra reference for its temp array */
+ ck_assert_int_eq(eina_model_refcount(c), 3);
+ fail_unless(eina_model_property_get(c, "x", &tmp));
+ fail_unless(eina_value_get(&tmp, &x));
+ ck_assert_int_eq(x, i);
+
+ eina_model_unref(c);
+ i--;
+ }
+ ck_assert_int_eq(i, -1);
+ eina_iterator_free(it);
+
+ it = eina_model_child_sorted_iterator_get
+ (m, EINA_COMPARE_CB(eina_model_compare));
+ fail_unless(it != NULL);
+ i = 0;
+ EINA_ITERATOR_FOREACH(it, c)
+ {
+ Eina_Value tmp;
+ int x;
+
+ /* 3 because sort takes an extra reference for its temp array */
+ ck_assert_int_eq(eina_model_refcount(c), 3);
+ fail_unless(eina_model_property_get(c, "x", &tmp));
+ fail_unless(eina_value_get(&tmp, &x));
+ ck_assert_int_eq(x, i);
+
+ eina_model_unref(c);
+ i++;
+ }
+ ck_assert_int_eq(i, 5);
+ eina_iterator_free(it);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+ ck_assert_int_eq(count_del, 6);
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Bool
+eina_model_test_filter_event(const void *m, void *c, void *fdata)
+{
+ Eina_Value tmp;
+ int x;
+ fail_unless(m == fdata);
+ fail_unless(eina_model_property_get(c, "x", &tmp));
+ fail_unless(eina_value_get(&tmp, &x));
+ eina_value_flush(&tmp);
+ return x % 2 == 0;
+}
+
+START_TEST(eina_model_test_child_filtered_iterator)
+{
+ unsigned int count_del = 0;
+ Eina_Iterator *it;
+ Eina_Model *m;
+ int i = 0, idx;
+
+ eina_init();
+
+ m = eina_model_test_iterator_setup(&count_del);
+
+ it = eina_model_child_filtered_iterator_get
+ (m, eina_model_test_filter_event, m);
+ fail_unless(it != NULL);
+ EINA_ITERATOR_FOREACH(it, idx)
+ {
+ Eina_Model *c;
+ Eina_Value tmp;
+ int x;
+
+ ck_assert_int_eq(idx % 2, 0);
+ ck_assert_int_eq(idx, i);
+
+ c = eina_model_child_get(m, idx);
+ fail_unless(c != NULL);
+ ck_assert_int_eq(eina_model_refcount(c), 2);
+ fail_unless(eina_model_property_get(c, "x", &tmp));
+ fail_unless(eina_value_get(&tmp, &x));
+ ck_assert_int_eq(x, i);
+
+ eina_model_unref(c);
+ i += 2;
+ }
+ ck_assert_int_eq(i, 6);
+ eina_iterator_free(it);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+ ck_assert_int_eq(count_del, 6);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_model_test_struct)
+{
+ unsigned int count_del = 0, count_pset = 0, count_pdel = 0;
+ Eina_Model *m;
+ struct myst {
+ int i;
+ char c;
+ };
+ const Eina_Value_Struct_Member myst_members[] = {
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct myst, i),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_CHAR, struct myst, c)
+ };
+ const Eina_Value_Struct_Desc myst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ NULL, myst_members, EINA_C_ARRAY_LENGTH(myst_members), sizeof(struct myst)
+ };
+ Eina_Value inv, outv;
+ int i;
+ char c, *s;
+ Eina_List *lst;
+ Eina_Bool ck;
+
+ eina_init();
+
+ m = eina_model_struct_new(&myst_desc);
+ fail_unless(m != NULL);
+
+ eina_model_event_callback_add
+ (m, "deleted", _eina_test_model_cb_count, &count_del);
+ eina_model_event_callback_add
+ (m, "property,set", _eina_test_model_cb_count, &count_pset);
+ eina_model_event_callback_add
+ (m, "property,deleted", _eina_test_model_cb_count, &count_pdel);
+
+ fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&inv, 1234));
+ fail_unless(eina_value_get(&inv, &i));
+ ck_assert_int_eq(i, 1234);
+ fail_unless(eina_model_property_set(m, "i", &inv));
+
+ eina_value_flush(&inv);
+ fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_CHAR));
+ fail_unless(eina_value_set(&inv, 33));
+ fail_unless(eina_value_get(&inv, &c));
+ ck_assert_int_eq(c, 33);
+ fail_unless(eina_model_property_set(m, "c", &inv));
+
+ lst = eina_model_properties_names_list_get(m);
+ ck_assert_int_eq(eina_list_count(lst), 2);
+
+ lst = eina_list_sort(lst, 0, EINA_COMPARE_CB(strcmp));
+ ck_assert_str_eq("c", eina_list_nth(lst, 0));
+ ck_assert_str_eq("i", eina_list_nth(lst, 1));
+
+ eina_model_properties_names_list_free(lst);
+
+ fail_unless(eina_model_property_get(m, "i", &outv));
+ fail_unless(outv.type == EINA_VALUE_TYPE_INT);
+ fail_unless(eina_value_get(&outv, &i));
+ ck_assert_int_eq(i, 1234);
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "c", &outv));
+ fail_unless(outv.type == EINA_VALUE_TYPE_CHAR);
+ fail_unless(eina_value_get(&outv, &c));
+ ck_assert_int_eq(c, 33);
+ eina_value_flush(&outv);
+
+ eina_value_flush(&inv);
+
+ /* negative test (check safety was displayed by using print_cb) */
+ eina_log_print_cb_set(_eina_test_model_check_safety_null, &ck);
+
+ fail_if(eina_model_property_get(m, "non-existent", &outv));
+
+ ck = EINA_FALSE;
+ fail_if(eina_model_property_get(m, NULL, &outv));
+ fail_unless(ck == EINA_TRUE);
+
+ fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_STRING));
+ fail_unless(eina_value_set(&inv, "hello world"));
+
+ eina_log_print_cb_set(_eina_test_model_check_safety_false, &ck);
+
+ ck = EINA_FALSE;
+ fail_if(eina_model_property_set(m, "i", &inv));
+ fail_unless(ck == EINA_TRUE);
+
+ ck = EINA_FALSE;
+ fail_if(eina_model_property_set(m, "c", &inv));
+ fail_unless(ck == EINA_TRUE);
+
+ /* revert print_cb to default */
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+
+ fail_if(eina_model_property_del(m, "value"));
+ fail_if(eina_model_property_del(m, "i"));
+ fail_if(eina_model_property_del(m, "c"));
+
+ eina_value_flush(&inv);
+
+ s = eina_model_to_string(m);
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "Eina_Model_Type_Struct({c: 33, i: 1234}, [])");
+ free(s);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+
+ eina_model_unref(m);
+ ck_assert_int_eq(count_del, 1);
+ ck_assert_int_eq(count_pset, 2);
+ ck_assert_int_eq(count_pdel, 0);
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Bool
+_struct_complex_members_constructor(Eina_Model *m)
+{
+ struct myst {
+ Eina_Value_Array a;
+ Eina_Value_List l;
+ Eina_Value_Hash h;
+ Eina_Value_Struct s;
+ } st;
+ struct subst {
+ int i, j;
+ };
+ static Eina_Value_Struct_Member myst_members[] = {
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, a),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, l),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, h),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, s)
+ };
+ static Eina_Value_Struct_Desc myst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ NULL, myst_members, EINA_C_ARRAY_LENGTH(myst_members), sizeof(struct myst)
+ };
+ static Eina_Value_Struct_Member subst_members[] = {
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct subst, i),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct subst, j)
+ };
+ static Eina_Value_Struct_Desc subst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ NULL, subst_members, EINA_C_ARRAY_LENGTH(subst_members),
+ sizeof(struct subst)
+ };
+
+ if (!myst_members[0].type)
+ {
+ myst_members[0].type = EINA_VALUE_TYPE_ARRAY;
+ myst_members[1].type = EINA_VALUE_TYPE_LIST;
+ myst_members[2].type = EINA_VALUE_TYPE_HASH;
+ myst_members[3].type = EINA_VALUE_TYPE_STRUCT;
+ }
+
+ if (!subst_members[0].type)
+ {
+ subst_members[0].type = EINA_VALUE_TYPE_INT;
+ subst_members[1].type = EINA_VALUE_TYPE_INT;
+ }
+
+ if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, m))
+ return EINA_FALSE;
+
+ memset(&st, 0, sizeof(st));
+
+ st.a.subtype = EINA_VALUE_TYPE_STRING;
+ st.l.subtype = EINA_VALUE_TYPE_STRING;
+ st.h.subtype = EINA_VALUE_TYPE_STRING;
+ st.s.desc = &subst_desc;
+ if (!eina_model_struct_set(m, &myst_desc, &st))
+ return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_model_test_struct_complex_members)
+{
+ Eina_Model *m;
+ Eina_Value outv;
+ char *s;
+ Eina_Model_Type type = EINA_MODEL_TYPE_INIT_NOPRIVATE
+ ("struct_complex_members", Eina_Model_Type, NULL, NULL, NULL);
+
+ eina_init();
+
+ type.constructor = _struct_complex_members_constructor;
+ type.parent = EINA_MODEL_TYPE_STRUCT;
+
+ m = eina_model_new(&type);
+ fail_unless(m != NULL);
+
+ fail_unless(eina_model_property_get(m, "a", &outv));
+ fail_unless(eina_value_array_append(&outv, "Hello"));
+ fail_unless(eina_value_array_append(&outv, "World"));
+ fail_unless(eina_model_property_set(m, "a", &outv));
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "l", &outv));
+ fail_unless(eina_value_list_append(&outv, "Some"));
+ fail_unless(eina_value_list_append(&outv, "Thing"));
+ fail_unless(eina_model_property_set(m, "l", &outv));
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "h", &outv));
+ fail_unless(eina_value_hash_set(&outv, "key", "value"));
+ fail_unless(eina_model_property_set(m, "h", &outv));
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "s", &outv));
+ fail_unless(eina_value_struct_set(&outv, "i", 1234));
+ fail_unless(eina_value_struct_set(&outv, "j", 44));
+ fail_unless(eina_model_property_set(m, "s", &outv));
+ eina_value_flush(&outv);
+
+ s = eina_model_to_string(m);
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "struct_complex_members({a: [Hello, World], h: {key: value}, l: [Some, Thing], s: {i: 1234, j: 44}}, [])");
+ free(s);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+
+ eina_model_unref(m);
+ eina_shutdown();
+}
+END_TEST
+
+typedef struct _Animal_Type
+{
+ Eina_Model_Type parent_class;
+ void (*eat)(Eina_Model *mdl);
+} Animal_Type;
+
+typedef struct _Human_Type
+{
+ Animal_Type parent_class;
+ void (*talk)(Eina_Model *mdl);
+} Human_Type;
+
+typedef struct _Pooper_Interface
+{
+ Eina_Model_Interface base_interface;
+ void (*poop)(Eina_Model *mdl);
+} Pooper_Interface;
+
+#define ANIMAL_TYPE(x) ((Animal_Type *) x)
+#define HUMAN_TYPE(x) ((Human_Type *) x)
+#define POOPER_IFACE(x) ((Pooper_Interface *) x)
+#define POOPER_IFACE_NAME "Pooper_Interace"
+
+#define INHER_CB_COUNT(prefix) \
+static int prefix ## _count = 0; \
+static void \
+prefix (Eina_Model *mdl) \
+{ \
+ (void) mdl; \
+ (prefix ## _count)++; \
+}
+
+static void
+animal_eat(Eina_Model *mdl)
+{
+ void (*pf)(Eina_Model *mdl);
+ pf = eina_model_method_resolve(mdl, Animal_Type, eat);
+ EINA_SAFETY_ON_NULL_RETURN(pf);
+ pf(mdl);
+}
+
+static void
+pooper_poop(Eina_Model *mdl)
+{
+ const Eina_Model_Interface *iface = NULL;
+ iface = eina_model_interface_get(mdl, POOPER_IFACE_NAME);
+
+ EINA_SAFETY_ON_NULL_RETURN(iface);
+
+ void (*pf)(Eina_Model *);
+
+ pf = eina_model_interface_method_resolve(iface, mdl, Pooper_Interface, poop);
+ EINA_SAFETY_ON_NULL_RETURN(pf);
+ pf(mdl);
+}
+
+INHER_CB_COUNT(_animal_poop);
+INHER_CB_COUNT(_human_poop);
+INHER_CB_COUNT(_animal_eat);
+INHER_CB_COUNT(_human_eat);
+
+START_TEST(eina_model_test_inheritance)
+{
+ eina_init();
+
+ Pooper_Interface _ANIMAL_POOPER_IFACE;
+ Eina_Model_Interface *ANIMAL_POOPER_IFACE = (Eina_Model_Interface *) &_ANIMAL_POOPER_IFACE;
+ memset(&_ANIMAL_POOPER_IFACE, 0, sizeof(_ANIMAL_POOPER_IFACE));
+ ANIMAL_POOPER_IFACE->version = EINA_MODEL_INTERFACE_VERSION;
+ ANIMAL_POOPER_IFACE->interface_size = sizeof(Pooper_Interface);
+ ANIMAL_POOPER_IFACE->name = POOPER_IFACE_NAME;
+ POOPER_IFACE(ANIMAL_POOPER_IFACE)->poop = _animal_poop;
+
+ Pooper_Interface _HUMAN_POOPER_IFACE;
+ Eina_Model_Interface *HUMAN_POOPER_IFACE = (Eina_Model_Interface *) &_HUMAN_POOPER_IFACE;
+ const Eina_Model_Interface *HUMAN_POOPER_IFACES[] = {
+ ANIMAL_POOPER_IFACE, NULL
+ };
+ memset(&_HUMAN_POOPER_IFACE, 0, sizeof(_HUMAN_POOPER_IFACE));
+ HUMAN_POOPER_IFACE->version = EINA_MODEL_INTERFACE_VERSION;
+ HUMAN_POOPER_IFACE->interface_size = sizeof(Pooper_Interface);
+ HUMAN_POOPER_IFACE->name = POOPER_IFACE_NAME;
+ HUMAN_POOPER_IFACE->interfaces = HUMAN_POOPER_IFACES;
+ POOPER_IFACE(HUMAN_POOPER_IFACE)->poop = _human_poop;
+
+ const Eina_Model_Interface *ANIMAL_IFACES[] = {ANIMAL_POOPER_IFACE, NULL};
+ const Eina_Model_Interface *HUMAN_IFACES[] = {HUMAN_POOPER_IFACE, NULL};
+
+ /* Init Animal Type */
+ Animal_Type _ANIMAL_TYPE;
+ Eina_Model_Type *ANIMAL_TYPE = (Eina_Model_Type *) &_ANIMAL_TYPE;
+
+ memset(&_ANIMAL_TYPE, 0, sizeof(_ANIMAL_TYPE));
+ Eina_Model_Type *type = (Eina_Model_Type *) &_ANIMAL_TYPE;
+ type->version = EINA_MODEL_TYPE_VERSION;
+ type->parent = EINA_MODEL_TYPE_BASE;
+ type->type_size = sizeof(Animal_Type);
+ type->name = "Animal_Type";
+ type->parent = EINA_MODEL_TYPE_GENERIC;
+ type->interfaces = ANIMAL_IFACES;
+
+ ANIMAL_TYPE(type)->eat = _animal_eat;
+
+ /* Init Human Type */
+ Animal_Type _HUMAN_TYPE;
+ Eina_Model_Type *HUMAN_TYPE = (Eina_Model_Type *) &_HUMAN_TYPE;
+ memset(&_HUMAN_TYPE, 0, sizeof(_HUMAN_TYPE));
+ type = (Eina_Model_Type *) &_HUMAN_TYPE;
+ type->version = EINA_MODEL_TYPE_VERSION;
+ type->parent = ANIMAL_TYPE;
+ type->type_size = sizeof(Human_Type);
+ type->name = "Human_Type";
+ type->interfaces = HUMAN_IFACES;
+
+ ANIMAL_TYPE(type)->eat = _human_eat;
+
+ Eina_Model *hm, *am;
+ am = eina_model_new(ANIMAL_TYPE);
+ hm = eina_model_new(HUMAN_TYPE);
+
+ animal_eat(am);
+ ck_assert_int_eq(_animal_eat_count, 1);
+ animal_eat(hm);
+ ck_assert_int_eq(_human_eat_count, 1);
+
+ pooper_poop(am);
+ ck_assert_int_eq(_animal_poop_count, 1);
+ pooper_poop(hm);
+ ck_assert_int_eq(_human_poop_count, 1);
+
+ ck_assert_int_eq(_animal_eat_count, 1);
+ ck_assert_int_eq(_human_eat_count, 1);
+ ck_assert_int_eq(_animal_poop_count, 1);
+ ck_assert_int_eq(_human_poop_count, 1);
+
+ ck_assert_int_eq(eina_model_refcount(am), 1);
+ ck_assert_int_eq(eina_model_refcount(hm), 1);
+
+ eina_model_unref(am);
+ eina_model_unref(hm);
+
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Bool
+_myproperties_load(Eina_Model *m)
+{
+ Eina_Value v;
+ Eina_Bool ret;
+ int count;
+
+ if (!eina_model_property_get(m, "load_count", &v))
+ return EINA_FALSE;
+
+ eina_value_get(&v, &count);
+ count++;
+ eina_value_set(&v, count);
+
+ ret = eina_model_property_set(m, "load_count", &v);
+ eina_value_flush(&v);
+
+ return ret;
+}
+
+static Eina_Bool
+_myproperties_unload(Eina_Model *m)
+{
+ Eina_Value v;
+ Eina_Bool ret;
+ int count;
+
+ if (!eina_model_property_get(m, "load_count", &v))
+ return EINA_FALSE;
+
+ eina_value_get(&v, &count);
+ count--;
+ eina_value_set(&v, count);
+
+ ret = eina_model_property_set(m, "load_count", &v);
+ eina_value_flush(&v);
+
+ return ret;
+}
+
+static Eina_Bool
+_mychildren_load(Eina_Model *m)
+{
+ Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ int ret = eina_model_child_append(m, c);
+ eina_model_unref(c);
+ return ret >= 0;
+}
+
+static Eina_Bool
+_mychildren_unload(Eina_Model *m)
+{
+ int count = eina_model_child_count(m);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(count > 0, EINA_FALSE);
+ return eina_model_child_del(m, count - 1);
+}
+
+START_TEST(eina_model_test_ifaces_load_unload)
+{
+ unsigned int count_loaded = 0, count_unloaded = 0;
+ unsigned int count_ploaded = 0, count_punloaded = 0;
+ unsigned int count_cloaded = 0, count_cunloaded = 0;
+ static Eina_Model_Interface_Properties piface;
+ static Eina_Model_Interface_Children ciface;
+ static const Eina_Model_Interface *piface_parents[2] = {NULL, NULL};
+ static const Eina_Model_Interface *ciface_parents[2] = {NULL, NULL};
+ static const Eina_Model_Interface *type_ifaces[3] = {
+ &piface.base, &ciface.base, NULL
+ };
+ static Eina_Model_Type type;
+ Eina_Model *m;
+ Eina_Value v;
+ int count;
+
+ eina_init();
+
+ /* do after eina_init() otherwise interfaces are not set */
+ piface_parents[0] = EINA_MODEL_INTERFACE_PROPERTIES_HASH;
+ ciface_parents[0] = EINA_MODEL_INTERFACE_CHILDREN_INARRAY;
+
+ memset(&piface, 0, sizeof(piface));
+ piface.base.version = EINA_MODEL_INTERFACE_VERSION;
+ piface.base.interface_size = sizeof(piface);
+ piface.base.name = EINA_MODEL_INTERFACE_NAME_PROPERTIES;
+ piface.base.interfaces = piface_parents;
+ piface.load = _myproperties_load;
+ piface.unload = _myproperties_unload;
+
+ memset(&ciface, 0, sizeof(ciface));
+ ciface.base.version = EINA_MODEL_INTERFACE_VERSION;
+ ciface.base.interface_size = sizeof(ciface);
+ ciface.base.name = EINA_MODEL_INTERFACE_NAME_CHILDREN;
+ ciface.base.interfaces = ciface_parents;
+ ciface.load = _mychildren_load;
+ ciface.unload = _mychildren_unload;
+
+ type.version = EINA_MODEL_TYPE_VERSION;
+ type.private_size = 0;
+ type.name = "MyType";
+ eina_model_type_subclass_setup(&type, EINA_MODEL_TYPE_GENERIC);
+ type.interfaces = type_ifaces;
+
+ m = eina_model_new(&type);
+ fail_unless(m != NULL);
+
+ eina_model_event_callback_add
+ (m, "loaded", _eina_test_model_cb_count, &count_loaded);
+ eina_model_event_callback_add
+ (m, "unloaded", _eina_test_model_cb_count, &count_unloaded);
+
+ eina_model_event_callback_add
+ (m, "properties,loaded", _eina_test_model_cb_count, &count_ploaded);
+ eina_model_event_callback_add
+ (m, "properties,unloaded", _eina_test_model_cb_count, &count_punloaded);
+
+ eina_model_event_callback_add
+ (m, "children,loaded", _eina_test_model_cb_count, &count_cloaded);
+ eina_model_event_callback_add
+ (m, "children,unloaded", _eina_test_model_cb_count, &count_cunloaded);
+
+ fail_unless(eina_value_setup(&v, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&v, 0));
+ fail_unless(eina_model_property_set(m, "load_count", &v));
+ eina_value_flush(&v);
+
+ fail_unless(eina_model_load(m));
+ fail_unless(eina_model_load(m));
+ fail_unless(eina_model_load(m));
+
+ /* each load increments one for load_count property */
+ fail_unless(eina_model_property_get(m, "load_count", &v));
+ fail_unless(eina_value_pget(&v, &count));
+ ck_assert_int_eq(count, 3);
+ eina_value_flush(&v);
+
+ /* each load adds one child */
+ ck_assert_int_eq(eina_model_child_count(m), 3);
+
+ fail_unless(eina_model_unload(m));
+ fail_unless(eina_model_unload(m));
+ fail_unless(eina_model_unload(m));
+
+ ck_assert_int_eq(count_loaded, 3);
+ ck_assert_int_eq(count_unloaded, 3);
+
+ ck_assert_int_eq(count_ploaded, 3);
+ ck_assert_int_eq(count_punloaded, 3);
+
+ ck_assert_int_eq(count_cloaded, 3);
+ ck_assert_int_eq(count_cunloaded, 3);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+ eina_model_unref(m);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_model(TCase *tc)
+{
+ tcase_add_test(tc, eina_model_test_properties);
+ tcase_add_test(tc, eina_model_test_children);
+ tcase_add_test(tc, eina_model_test_copy);
+ tcase_add_test(tc, eina_model_test_deep_copy);
+ tcase_add_test(tc, eina_model_test_child_iterator);
+ tcase_add_test(tc, eina_model_test_child_reversed_iterator);
+ tcase_add_test(tc, eina_model_test_child_sorted_iterator);
+ tcase_add_test(tc, eina_model_test_child_filtered_iterator);
+ tcase_add_test(tc, eina_model_test_struct);
+ tcase_add_test(tc, eina_model_test_struct_complex_members);
+ tcase_add_test(tc, eina_model_test_inheritance);
+ tcase_add_test(tc, eina_model_test_ifaces_load_unload);
+}
diff --git a/src/tests/eina/eina_test_module.c b/src/tests/eina/eina_test_module.c
new file mode 100644
index 000000000..56bdca7bc
--- /dev/null
+++ b/src/tests/eina/eina_test_module.c
@@ -0,0 +1,70 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static Eina_Bool list_cb(Eina_Module *m, void *data __UNUSED__)
+{
+ int *sym;
+ const char *file;
+
+ /* the reference count */
+ eina_module_load(m);
+ /* get */
+ sym = eina_module_symbol_get(m, "dummy_symbol");
+ fail_if(!sym);
+ fail_if(*sym != 0xbad);
+ file = eina_module_file_get(m);
+ fail_if(!file);
+ eina_module_unload(m);
+
+ return EINA_TRUE;
+}
+
+
+START_TEST(eina_module_load_unload)
+{
+ Eina_Array *_modules;
+
+ eina_init();
+ _modules = eina_module_list_get(NULL,
+ PACKAGE_BUILD_DIR "/src/tests/",
+ EINA_TRUE,
+ &list_cb,
+ NULL);
+ fail_if(!_modules);
+ eina_module_list_load(_modules);
+ eina_module_list_unload(_modules);
+ eina_module_list_free(_modules);
+ /* TODO delete the list */
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_module(TCase *tc)
+{
+ tcase_add_test(tc, eina_module_load_unload);
+}
diff --git a/src/tests/eina/eina_test_module_dummy.c b/src/tests/eina/eina_test_module_dummy.c
new file mode 100644
index 000000000..d42b530f7
--- /dev/null
+++ b/src/tests/eina/eina_test_module_dummy.c
@@ -0,0 +1,22 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "Eina.h"
+
+Eina_Bool dummy_module_init(void)
+{
+ return EINA_TRUE;
+}
+
+void dummy_module_shutdown(void)
+{
+
+}
+
+EAPI int dummy_symbol = 0xbad;
+
+EINA_MODULE_INIT(dummy_module_init);
+EINA_MODULE_SHUTDOWN(dummy_module_shutdown);
diff --git a/src/tests/eina/eina_test_quadtree.c b/src/tests/eina/eina_test_quadtree.c
new file mode 100644
index 000000000..52faeec3c
--- /dev/null
+++ b/src/tests/eina/eina_test_quadtree.c
@@ -0,0 +1,195 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2010 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static Eina_Quad_Direction
+_eina_quadtree_rectangle_vert(const void *object, size_t middle)
+{
+ const Eina_Rectangle *r = object;
+
+ if (r->y + r->h < (int)middle)
+ return EINA_QUAD_LEFT;
+
+ if (r->y > (int)middle)
+ return EINA_QUAD_RIGHT;
+
+ return EINA_QUAD_BOTH;
+}
+
+static Eina_Quad_Direction
+_eina_quadtree_rectangle_hort(const void *object, size_t middle)
+{
+ const Eina_Rectangle *r = object;
+
+ if (r->x + r->w < (int)middle)
+ return EINA_QUAD_LEFT;
+
+ if (r->x > (int)middle)
+ return EINA_QUAD_RIGHT;
+
+ return EINA_QUAD_BOTH;
+}
+
+START_TEST(eina_quadtree_collision)
+{
+ struct
+ {
+ Eina_Rectangle r;
+ Eina_QuadTree_Item *item;
+ } objects[] = {
+ { { 10, 10, 30, 30 }, NULL },
+ { { 20, 20, 30, 30 }, NULL },
+ { { 5, 30, 30, 30 }, NULL },
+ { { 70, 130, 100, 100 }, NULL },
+ { { 10, 220, 50, 40 }, NULL },
+ { { 310, 20, 50, 30 }, NULL },
+ { { 300, 220, 40, 40 }, NULL },
+ { { 500, 150, 40, 40 }, NULL },
+ { { 500, 220, 40, 40 }, NULL },
+ { { 330, 250, 40, 40 }, NULL },
+ { { 300, 400, 40, 40 }, NULL },
+ { { 10, 400, 40, 40 }, NULL },
+ { { 0, 0, 0, 0 }, NULL }
+ };
+ struct
+ {
+ Eina_Rectangle r;
+ int count;
+ int result[20];
+ } tests [] = {
+ { { 600, 400, 40, 40 }, 4, { 4, 6, 8, 10 } },
+ { { 20, 30, 10, 10 }, 7, { 0, 1, 2, 4, 5, 6, 8 } },
+ { { 0, 0, 0, 0 }, -1, {} },
+ };
+ int hidden[] = { 4, 5, 6, 8, 10 };
+ int show[] = { 0, 1, 2 };
+ Eina_QuadTree *q;
+ Eina_Inlist *head;
+ Eina_Rectangle *r;
+ int count;
+ int i;
+
+ fail_if(!eina_init());
+
+ q = eina_quadtree_new(640, 480,
+ _eina_quadtree_rectangle_vert,
+ _eina_quadtree_rectangle_hort);
+
+ fail_if(!q);
+
+ for (i = 0; objects[i].r.w != 0 && objects[i].r.h != 0; ++i)
+ {
+ objects[i].item = eina_quadtree_add(q, &objects[i].r);
+ fail_if(!objects[i].item);
+ fail_if(!eina_quadtree_show(objects[i].item));
+ }
+
+ eina_quadtree_resize(q, 640, 480);
+
+ for (i = 0; tests[i].count != -1; ++i)
+ {
+ head = eina_quadtree_collide(q,
+ tests[i].r.x, tests[i].r.y,
+ tests[i].r.w, tests[i].r.h);
+
+ count = 0;
+ while (head)
+ {
+ int k;
+
+ r = eina_quadtree_object(head);
+
+ for (k = 0; k < tests[i].count; ++k)
+ {
+ if (&objects[tests[i].result[k]].r == r)
+ break;
+ }
+ fail_if(k == tests[i].count);
+
+ head = head->next;
+ count++;
+ }
+ fail_if(count != tests[i].count);
+ }
+
+ for (i = 0; i < (int)(sizeof (hidden) / sizeof (int)); ++i)
+ eina_quadtree_hide(objects[hidden[i]].item);
+ for (i = 0; i < (int)(sizeof (show) / sizeof (int)); ++i)
+ eina_quadtree_show(objects[show[i]].item);
+
+ head = eina_quadtree_collide(q,
+ tests[1].r.x, tests[1].r.y,
+ tests[1].r.w, tests[1].r.h);
+
+ count = 0;
+ while (head)
+ {
+ r = eina_quadtree_object(head);
+
+ fail_if(r != &objects[tests[1].result[show[count]]].r);
+
+ head = head->next;
+ count++;
+ }
+ fail_if(count != 3);
+
+ eina_quadtree_cycle(q);
+ eina_quadtree_show(objects[4].item);
+ eina_quadtree_increase(objects[4].item);
+ eina_quadtree_show(objects[5].item);
+ eina_quadtree_increase(objects[5].item);
+ eina_quadtree_del(objects[5].item);
+ eina_quadtree_change(objects[10].item);
+ eina_quadtree_increase(objects[10].item);
+
+ eina_quadtree_resize(q, 641, 480);
+
+ head = eina_quadtree_collide(q,
+ tests[0].r.x, tests[0].r.y,
+ tests[0].r.w, tests[0].r.h);
+
+ count = 0;
+ while (head)
+ {
+ r = eina_quadtree_object(head);
+
+ head = head->next;
+ count++;
+ }
+ fail_if(count != 1);
+
+ eina_quadtree_free(q);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_quadtree(TCase *tc)
+{
+ tcase_add_test(tc, eina_quadtree_collision);
+}
diff --git a/src/tests/eina/eina_test_rbtree.c b/src/tests/eina/eina_test_rbtree.c
new file mode 100644
index 000000000..fabe2bfd2
--- /dev/null
+++ b/src/tests/eina/eina_test_rbtree.c
@@ -0,0 +1,452 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static inline Eina_Bool
+_eina_rbtree_is_red(Eina_Rbtree *tree)
+{
+ return tree != NULL && tree->color == EINA_RBTREE_RED;
+}
+
+static int
+_eina_rbtree_black_height(Eina_Rbtree *tree, Eina_Rbtree_Cmp_Node_Cb cmp)
+{
+ Eina_Rbtree *left;
+ Eina_Rbtree *right;
+ Eina_Rbtree_Direction dir;
+ int left_height;
+ int right_height;
+
+ if (!tree)
+ return 1;
+
+ left = tree->son[EINA_RBTREE_LEFT];
+ right = tree->son[EINA_RBTREE_RIGHT];
+
+ /* Consecutive red links. */
+ fail_if(_eina_rbtree_is_red(tree) &&
+ (_eina_rbtree_is_red(left) || _eina_rbtree_is_red(right)));
+
+ left_height = _eina_rbtree_black_height(left, cmp);
+ right_height = _eina_rbtree_black_height(right, cmp);
+
+ /* Check binary search tree. */
+ if (left)
+ {
+ dir = cmp(tree, left, NULL);
+ fail_if(dir != EINA_RBTREE_LEFT);
+ }
+
+ if (right)
+ {
+ dir = cmp(tree, right, NULL);
+ fail_if(dir != EINA_RBTREE_RIGHT);
+ }
+
+ /* Check black height */
+ if (left_height != right_height)
+ fprintf(stderr, "%i != %i\n", left_height, right_height);
+
+ fail_if(left_height != right_height);
+
+ return _eina_rbtree_is_red(tree) ? left_height : left_height + 1;
+}
+
+typedef struct _Eina_Rbtree_Int Eina_Rbtree_Int;
+struct _Eina_Rbtree_Int
+{
+ Eina_Rbtree node;
+ int value;
+};
+
+static Eina_Rbtree_Direction
+eina_rbtree_int_cmp(const Eina_Rbtree_Int *left,
+ const Eina_Rbtree_Int *right,
+ __UNUSED__ void *data)
+{
+ fail_if(!left);
+ fail_if(!right);
+
+ if (left->value < right->value)
+ return EINA_RBTREE_LEFT;
+
+ return EINA_RBTREE_RIGHT;
+}
+
+static int
+eina_rbtree_int_key(const Eina_Rbtree_Int *node,
+ const int *key,
+ __UNUSED__ int length,
+ __UNUSED__ void *data)
+{
+ fail_if(!node);
+ return node->value - *key;
+}
+
+static Eina_Rbtree_Int *
+_eina_rbtree_int_new(int value)
+{
+ Eina_Rbtree_Int *it;
+
+ it = malloc(sizeof (Eina_Rbtree_Int));
+ fail_if(!it);
+
+ it->value = value;
+
+ return it;
+}
+
+START_TEST(eina_rbtree_insertion)
+{
+ Eina_Rbtree_Int *root = NULL;
+ Eina_Rbtree_Int *item;
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < 500; ++i)
+ {
+ item = _eina_rbtree_int_new(rand());
+ root = (Eina_Rbtree_Int *)eina_rbtree_inline_insert(
+ &root->node,
+ &item->node,
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp),
+ NULL);
+ }
+
+ _eina_rbtree_black_height(&root->node,
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp));
+}
+END_TEST
+
+START_TEST(eina_rbtree_lookup)
+{
+ Eina_Rbtree_Int *root = NULL;
+ Eina_Rbtree_Int *item;
+ int list[] = { 50, 100, 10, 43, 23 };
+ unsigned int i;
+
+ for (i = 0; i < sizeof (list) / sizeof (int); ++i)
+ {
+ item = _eina_rbtree_int_new(list[i]);
+ root = (Eina_Rbtree_Int *)eina_rbtree_inline_insert(
+ &root->node,
+ &item->node,
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp),
+ NULL);
+ }
+
+ item = (Eina_Rbtree_Int *)eina_rbtree_inline_lookup(&root->node,
+ &list[0],
+ sizeof(int),
+ EINA_RBTREE_CMP_KEY_CB(
+ eina_rbtree_int_key),
+ NULL);
+ fail_if(!item);
+
+ i = 42;
+ item =
+ (Eina_Rbtree_Int *)eina_rbtree_inline_lookup(&root->node,
+ &i,
+ sizeof(int),
+ EINA_RBTREE_CMP_KEY_CB(
+ eina_rbtree_int_key),
+ NULL);
+ fail_if(item);
+}
+END_TEST
+
+START_TEST(eina_rbtree_remove)
+{
+ Eina_Rbtree_Int *root = NULL;
+ Eina_Rbtree_Int *item;
+ Eina_Array *ea;
+ Eina_Array_Iterator it;
+ unsigned int i;
+
+ eina_init();
+
+ ea = eina_array_new(11);
+ fail_if(!ea);
+
+ srand(time(NULL));
+
+ for (i = 0; i < 500; ++i)
+ {
+ item = _eina_rbtree_int_new(rand());
+ eina_array_push(ea, item);
+ root = (Eina_Rbtree_Int *)eina_rbtree_inline_insert(
+ &root->node,
+ &item->node,
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp),
+ NULL);
+ }
+
+ _eina_rbtree_black_height(&root->node,
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+
+ EINA_ARRAY_ITER_NEXT(ea, i, item, it)
+ {
+ root = (Eina_Rbtree_Int *)eina_rbtree_inline_remove(
+ &root->node,
+ &item->node,
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp),
+ NULL);
+ _eina_rbtree_black_height(&root->node,
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+ }
+
+ fail_if(root != NULL);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_rbtree_simple_remove)
+{
+ Eina_Rbtree *root = NULL;
+ Eina_Rbtree *lookup;
+ int i;
+
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 10),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 42),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 69),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1337),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ _eina_rbtree_black_height(root,
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+
+ fail_if(root == NULL);
+
+ i = 69;
+ lookup = eina_rbtree_inline_lookup(root,
+ &i,
+ sizeof (int),
+ EINA_RBTREE_CMP_KEY_CB(
+ eina_rbtree_int_key),
+ NULL);
+ _eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+ fail_if(lookup == NULL);
+
+ root =
+ eina_rbtree_inline_remove(root, lookup, EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+
+ _eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+}
+END_TEST
+
+START_TEST(eina_rbtree_simple_remove2)
+{
+ Eina_Rbtree *root = NULL;
+ Eina_Rbtree *lookup;
+ int i;
+
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 10),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 42),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 69),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1337),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 77),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 75),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 81),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ _eina_rbtree_black_height(root,
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+
+ fail_if(root == NULL);
+
+ i = 69;
+ lookup = eina_rbtree_inline_lookup(root,
+ &i,
+ sizeof (int),
+ EINA_RBTREE_CMP_KEY_CB(
+ eina_rbtree_int_key),
+ NULL);
+ _eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+ fail_if(lookup == NULL);
+
+ root =
+ eina_rbtree_inline_remove(root, lookup, EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+
+ _eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+}
+END_TEST
+
+START_TEST(eina_rbtree_simple_remove3)
+{
+ Eina_Rbtree *root = NULL;
+ Eina_Rbtree *lookup;
+ int i;
+
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1113497590),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 499187507),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1693860487),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 26211080),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 797272577),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1252184882),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1448158229),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1821884856),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 346086006),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 936357333),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1462073936),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1717320055),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ root =
+ eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
+ 1845524606),
+ EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+ _eina_rbtree_black_height(root,
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+
+ fail_if(root == NULL);
+
+ i = 1113497590;
+ lookup = eina_rbtree_inline_lookup(root,
+ &i,
+ sizeof (int),
+ EINA_RBTREE_CMP_KEY_CB(
+ eina_rbtree_int_key),
+ NULL);
+ _eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+ fail_if(lookup == NULL);
+
+ root =
+ eina_rbtree_inline_remove(root, lookup, EINA_RBTREE_CMP_NODE_CB(
+ eina_rbtree_int_cmp), NULL);
+
+ _eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
+}
+END_TEST
+
+void
+eina_test_rbtree(TCase *tc)
+{
+ tcase_add_test(tc, eina_rbtree_insertion);
+ tcase_add_test(tc, eina_rbtree_lookup);
+ tcase_add_test(tc, eina_rbtree_remove);
+ tcase_add_test(tc, eina_rbtree_simple_remove);
+ tcase_add_test(tc, eina_rbtree_simple_remove2);
+ tcase_add_test(tc, eina_rbtree_simple_remove3);
+}
+
diff --git a/src/tests/eina/eina_test_rectangle.c b/src/tests/eina/eina_test_rectangle.c
new file mode 100644
index 000000000..581ab7613
--- /dev/null
+++ b/src/tests/eina/eina_test_rectangle.c
@@ -0,0 +1,115 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2007-2008 Cedric BAIL, Carsten Haitzler
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(eina_rectangle_pool)
+{
+ Eina_Rectangle_Pool *pool;
+ Eina_Rectangle *rects[8][8];
+ int x;
+ int y;
+ int w;
+ int h;
+
+ fail_if(!eina_init());
+
+ pool = eina_rectangle_pool_new(256, 256);
+ fail_if(pool == NULL);
+
+ eina_rectangle_pool_data_set(pool, rects);
+ fail_if(eina_rectangle_pool_data_get(pool) != rects);
+
+ fail_if(eina_rectangle_pool_request(pool, 1024, 1024) != NULL);
+
+ for (x = 0; x < 8; x++)
+ for (y = 0; y < 8; y++)
+ {
+ rects[x][y] = eina_rectangle_pool_request(pool, 32, 32);
+ fail_if(rects[x][y] == NULL);
+ }
+
+ fail_if(eina_rectangle_pool_count(pool) != 64);
+
+ fail_if(eina_rectangle_pool_get(rects[0][0]) != pool);
+
+ fail_if(eina_rectangle_pool_geometry_get(pool, &w, &h) != EINA_TRUE);
+ fail_if(w != 256 || h != 256);
+
+ fail_if(eina_rectangle_pool_request(pool, 32, 32) != NULL);
+ fail_if(eina_rectangle_pool_request(pool, 1024, 1024) != NULL);
+
+ for (x = 0; x < 8; x++)
+ eina_rectangle_pool_release(rects[0][x]);
+
+ fail_if(eina_rectangle_pool_request(pool, 16, 16) == NULL);
+
+ eina_rectangle_pool_free(pool);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_rectangle_intersect)
+{
+ Eina_Rectangle r1, r2, r3, r4, rd;
+
+ fail_if(!eina_init());
+
+ EINA_RECTANGLE_SET(&r1, 10, 10, 50, 50);
+ EINA_RECTANGLE_SET(&r2, 20, 20, 20, 20);
+ EINA_RECTANGLE_SET(&r3, 0, 0, 10, 10);
+ EINA_RECTANGLE_SET(&r4, 30, 30, 50, 50);
+
+ rd = r1;
+
+ fail_if(eina_rectangle_intersection(&rd, &r3));
+ fail_if(!eina_rectangle_intersection(&rd, &r2));
+
+ fail_if(rd.x != r2.x
+ || rd.y != r2.y
+ || rd.w != r2.w
+ || rd.h != r2.h);
+
+ rd = r1;
+
+ fail_if(!eina_rectangle_intersection(&rd, &r4));
+
+ fail_if(rd.x != 30
+ || rd.y != 30
+ || rd.w != 30
+ || rd.h != 30);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_rectangle(TCase *tc)
+{
+ tcase_add_test(tc, eina_rectangle_pool);
+ tcase_add_test(tc, eina_rectangle_intersect);
+}
+
diff --git a/src/tests/eina/eina_test_sched.c b/src/tests/eina/eina_test_sched.c
new file mode 100644
index 000000000..ff83a7efc
--- /dev/null
+++ b/src/tests/eina/eina_test_sched.c
@@ -0,0 +1,85 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if defined(EFL_HAVE_THREADS) && defined __linux__
+#include <pthread.h>
+#include <errno.h>
+#include <sys/resource.h>
+#endif
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+#if defined(EFL_HAVE_THREADS) && defined __linux__
+
+/*
+ * TODO: Test if RT priorities are right. However, make check should be run as
+ * root.
+ */
+
+static void *
+_thread_run(void *arg __UNUSED__)
+{
+ int niceval = getpriority(PRIO_PROCESS, 0);
+ int niceval2;
+ eina_sched_prio_drop();
+
+ niceval2 = getpriority(PRIO_PROCESS, 0);
+ fail_if((niceval2 != 19) && (niceval2 != niceval+5));
+
+ return NULL;
+}
+
+START_TEST(eina_test_sched_prio_drop)
+{
+ int niceval = getpriority(PRIO_PROCESS, 0);
+ int niceval2;
+ pthread_t tid;
+
+ eina_init();
+
+ pthread_create(&tid, NULL, _thread_run, NULL);
+
+ niceval2 = getpriority(PRIO_PROCESS, 0);
+ /* niceness of main thread should not have changed */
+ fail_if(niceval2 != niceval);
+
+ pthread_join(tid, NULL);
+ /* niceness of main thread should not have changed */
+ fail_if(niceval2 != niceval);
+
+ eina_shutdown();
+}
+END_TEST
+#else
+START_TEST(eina_test_sched_prio_drop)
+{
+ fprintf(stderr, "scheduler priority is not supported by your configuration.\n");
+}
+END_TEST
+#endif
+
+void
+eina_test_sched(TCase *tc)
+{
+ tcase_add_test(tc, eina_test_sched_prio_drop);
+}
diff --git a/src/tests/eina/eina_test_simple_xml_parser.c b/src/tests/eina/eina_test_simple_xml_parser.c
new file mode 100644
index 000000000..7093019e3
--- /dev/null
+++ b/src/tests/eina/eina_test_simple_xml_parser.c
@@ -0,0 +1,75 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(eina_simple_xml_parser_node_dump)
+{
+ FILE *f;
+
+ eina_init();
+ f = fopen("sample.gpx", "rb");
+ if (f)
+ {
+ long sz;
+
+ fseek(f, 0, SEEK_END);
+ sz = ftell(f);
+ if (sz > 0)
+ {
+ char *buf;
+
+ fseek(f, 0, SEEK_SET);
+ buf = malloc(sz + 1);
+ if (buf)
+ {
+ if (fread(buf, 1, sz, f))
+ {
+ Eina_Simple_XML_Node_Root *root = eina_simple_xml_node_load
+ (buf, sz, EINA_TRUE);
+ buf[sz] = '\0';
+ char *out = eina_simple_xml_node_dump(&root->base, " ");
+ //puts(out);
+ ck_assert_str_eq(out, buf);
+ free(out);
+ eina_simple_xml_node_root_free(root);
+ free(buf);
+ }
+ }
+ }
+ fclose(f);
+ }
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_simple_xml_parser(TCase *tc)
+{
+ tcase_add_test(tc, eina_simple_xml_parser_node_dump);
+}
diff --git a/src/tests/eina/eina_test_str.c b/src/tests/eina/eina_test_str.c
new file mode 100644
index 000000000..7fefc26d7
--- /dev/null
+++ b/src/tests/eina/eina_test_str.c
@@ -0,0 +1,187 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2010 Gustavo Sverzut Barbieri
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+ START_TEST(str_simple)
+{
+ eina_init();
+
+ fail_if(!eina_str_has_prefix("", ""));
+
+ fail_if(!eina_str_has_prefix("x", "x"));
+ fail_if(!eina_str_has_prefix("xab", "x"));
+ fail_if(!eina_str_has_prefix("xab", "xab"));
+
+ fail_if(eina_str_has_prefix("x", "xab"));
+ fail_if(eina_str_has_prefix("xab", "xyz"));
+ fail_if(eina_str_has_prefix("", "x"));
+ fail_if(eina_str_has_prefix("X", "x"));
+ fail_if(eina_str_has_prefix("xAb", "X"));
+ fail_if(eina_str_has_prefix("xAb", "xab"));
+
+
+ fail_if(!eina_str_has_suffix("", ""));
+
+ fail_if(!eina_str_has_suffix("x", "x"));
+ fail_if(!eina_str_has_suffix("abx", "x"));
+ fail_if(!eina_str_has_suffix("xab", "xab"));
+
+ fail_if(eina_str_has_suffix("x", "xab"));
+ fail_if(eina_str_has_suffix("xab", "xyz"));
+ fail_if(eina_str_has_suffix("", "x"));
+ fail_if(eina_str_has_suffix("X", "x"));
+ fail_if(eina_str_has_suffix("aBx", "X"));
+ fail_if(eina_str_has_suffix("xaB", "Xab"));
+
+
+ fail_if(!eina_str_has_extension("", ""));
+
+ fail_if(!eina_str_has_extension("x", "x"));
+ fail_if(!eina_str_has_extension("abx", "x"));
+ fail_if(!eina_str_has_extension("xab", "xab"));
+ fail_if(!eina_str_has_extension("x", "X"));
+ fail_if(!eina_str_has_extension("abx", "X"));
+ fail_if(!eina_str_has_extension("xab", "Xab"));
+ fail_if(!eina_str_has_extension("X", "X"));
+ fail_if(!eina_str_has_extension("aBx", "X"));
+ fail_if(!eina_str_has_extension("xaB", "Xab"));
+
+ fail_if(eina_str_has_extension("x", "xab"));
+ fail_if(eina_str_has_extension("xab", "xyz"));
+ fail_if(eina_str_has_extension("", "x"));
+ fail_if(eina_str_has_extension("x", "xAb"));
+ fail_if(eina_str_has_extension("xab", "xYz"));
+ fail_if(eina_str_has_extension("", "x"));
+
+ fail_if(eina_strlen_bounded("abc", 1024) != strlen("abc"));
+ fail_if(eina_strlen_bounded("abc", 2) != (size_t)-1);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(str_split)
+{
+ char **result;
+ unsigned int elements;
+
+ eina_init();
+
+ result = eina_str_split_full("nomatch", "", -1, &elements);
+ fail_if(result != NULL);
+ fail_if(elements != 0);
+
+ result = eina_str_split_full("nomatch", "x", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 1);
+ fail_if(strcmp(result[0], "nomatch") != 0);
+ fail_if(result[1]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full("nomatch", "xyz", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 1);
+ fail_if(strcmp(result[0], "nomatch") != 0);
+ fail_if(result[1]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full("match:match:match", ":", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 3);
+ for (elements = 0; elements < 3 - 1; elements++)
+ fail_if(strcmp(result[elements], "match") != 0);
+ fail_if(result[3]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full("a:b:c", ":", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 3);
+ fail_if(strcmp(result[0], "a") != 0);
+ fail_if(strcmp(result[1], "b") != 0);
+ fail_if(strcmp(result[2], "c") != 0);
+ fail_if(result[3]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full("a:b:", ":", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 3);
+ fail_if(strcmp(result[0], "a") != 0);
+ fail_if(strcmp(result[1], "b") != 0);
+ fail_if(strcmp(result[2], "") != 0);
+ fail_if(result[3]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full(":b:c", ":", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 3);
+ fail_if(strcmp(result[0], "") != 0);
+ fail_if(strcmp(result[1], "b") != 0);
+ fail_if(strcmp(result[2], "c") != 0);
+ fail_if(result[3]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full(":", ":", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 2);
+ fail_if(strcmp(result[0], "") != 0);
+ fail_if(strcmp(result[1], "") != 0);
+ fail_if(result[2]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full("a", "!!!!!!!!!", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 1);
+ fail_if(strcmp(result[0], "a") != 0);
+ fail_if(result[1]);
+ free(result[0]);
+ free(result);
+
+ result = eina_str_split_full("aaba", "ab", -1, &elements);
+ fail_if(result == NULL);
+ fail_if(elements != 2);
+ fail_if(strcmp(result[0], "a") != 0);
+ fail_if(strcmp(result[1], "a") != 0);
+ fail_if(result[2]);
+ free(result[0]);
+ free(result);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_str(TCase *tc)
+{
+ tcase_add_test(tc, str_simple);
+ tcase_add_test(tc, str_split);
+}
diff --git a/src/tests/eina/eina_test_strbuf.c b/src/tests/eina/eina_test_strbuf.c
new file mode 100644
index 000000000..2205e3e53
--- /dev/null
+++ b/src/tests/eina/eina_test_strbuf.c
@@ -0,0 +1,449 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2010 Sebastian Dransfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(strbuf_simple)
+{
+ Eina_Strbuf *buf;
+ char *txt;
+#define TEXT \
+ "This test should be so long that it is longer than the initial size of strbuf"
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ eina_strbuf_append(buf, TEXT);
+ fail_if(strcmp(eina_strbuf_string_get(buf), TEXT));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ eina_strbuf_append(buf, TEXT);
+ fail_if(strcmp(eina_strbuf_string_get(buf), TEXT TEXT));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ txt = eina_strbuf_string_steal(buf);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(txt, TEXT TEXT));
+ free(txt);
+ fail_if(eina_strbuf_length_get(buf) != 0);
+ fail_if(!strcmp(eina_strbuf_string_get(buf), TEXT TEXT));
+ eina_strbuf_append(buf, TEXT);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ eina_strbuf_reset(buf);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(eina_strbuf_length_get(buf) != 0);
+ fail_if(!strcmp(eina_strbuf_string_get(buf), TEXT));
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+#undef TEXT
+}
+END_TEST
+
+START_TEST(strbuf_manage_simple)
+{
+ Eina_Strbuf *buf;
+ char *txt;
+#define TEXT \
+ "This test should be so long that it is longer than the initial size of strbuf"
+
+ eina_init();
+
+ txt = strdup(TEXT);
+
+ buf = eina_strbuf_manage_new(txt);
+ fail_if(!buf);
+
+ fail_if(strcmp(eina_strbuf_string_get(buf), TEXT));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ eina_strbuf_append(buf, TEXT);
+ fail_if(strcmp(eina_strbuf_string_get(buf), TEXT TEXT));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ txt = eina_strbuf_string_steal(buf);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(txt, TEXT TEXT));
+ free(txt);
+ fail_if(eina_strbuf_length_get(buf) != 0);
+ fail_if(!strcmp(eina_strbuf_string_get(buf), TEXT TEXT));
+ eina_strbuf_append(buf, TEXT);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ eina_strbuf_reset(buf);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(eina_strbuf_length_get(buf) != 0);
+ fail_if(!strcmp(eina_strbuf_string_get(buf), TEXT));
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+#undef TEXT
+}
+END_TEST
+
+START_TEST(strbuf_remove)
+{
+ Eina_Strbuf *buf;
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ eina_strbuf_append(buf, "123 456 789 abc");
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ eina_strbuf_remove(buf, 0, 4);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "456 789 abc"));
+ eina_strbuf_remove(buf, 8, 1000);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "456 789 "));
+ eina_strbuf_remove(buf, 7, eina_strbuf_length_get(buf));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "456 789"));
+ eina_strbuf_remove(buf, 2, 4);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "45789"));
+ eina_strbuf_remove(buf, 4, 1);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "45789"));
+ eina_strbuf_remove(buf, 0, eina_strbuf_length_get(buf));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), ""));
+
+#define TEXT \
+ "This test should be so long that it is longer than the initial size of strbuf"
+ eina_strbuf_append(buf, TEXT TEXT);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ eina_strbuf_remove(buf, 0, eina_strbuf_length_get(buf) - 1);
+ fail_if(strcmp(eina_strbuf_string_get(buf), "f"));
+#undef TEXT
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(strbuf_append)
+{
+ Eina_Strbuf *buf;
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ eina_strbuf_append(buf, "abc");
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "abc"));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_append_escaped(buf, "abc");
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "abc"));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_append_escaped(buf, "abc '\\");
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "abc\\ \\'\\\\"));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_append_n(buf, "abc", 2);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "ab"));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_append_char(buf, 'a');
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "a"));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_append_length(buf, "something", strlen("something"));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "something"));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_append_length(buf, "somethingELSE", strlen("something"));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "something"));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(strbuf_insert)
+{
+ Eina_Strbuf *buf;
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ eina_strbuf_insert(buf, "abc", 10);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "abc"));
+
+ eina_strbuf_insert(buf, "123", 0);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "123abc"));
+
+ eina_strbuf_insert(buf, "xyz", eina_strbuf_length_get(buf));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "123abcxyz"));
+
+ eina_strbuf_insert(buf, "xyz", 1);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "1xyz23abcxyz"));
+
+ eina_strbuf_insert_n(buf, "ABCDEF", 2, 1);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "1ABxyz23abcxyz"));
+
+ eina_strbuf_insert_n(buf, "EINA", 2, 3);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "1ABEIxyz23abcxyz"));
+
+ eina_strbuf_insert_escaped(buf, "678", 3);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strncmp(eina_strbuf_string_get(buf) + 3, "678", 3));
+
+ eina_strbuf_insert_escaped(buf, "089 '\\", 9);
+ fail_if(strlen(eina_strbuf_string_get(
+ buf)) != eina_strbuf_length_get(buf));
+ fail_if(strncmp(eina_strbuf_string_get(buf) + 9,
+ "089\\ \\'\\\\",
+ strlen("089\\ \\'\\\\")));
+ eina_strbuf_reset(buf);
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(strbuf_replace)
+{
+ Eina_Strbuf *buf;
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ eina_strbuf_append(buf, "aaa");
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "aaa"));
+
+ fail_if(!eina_strbuf_replace(buf, "a", "b", 1));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "baa"));
+
+ fail_if(eina_strbuf_replace_all(buf, "a", "b") != 2);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "bbb"));
+
+ fail_if(!eina_strbuf_replace(buf, "b", "cc", 2));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "bccb"));
+
+ fail_if(eina_strbuf_replace_all(buf, "c", "aa") != 2);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "baaaab"));
+
+ fail_if(eina_strbuf_replace(buf, "c", "aa", 0));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "baaaab"));
+
+ fail_if(eina_strbuf_replace(buf, "c", "aa", 2));
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "baaaab"));
+
+ fail_if(eina_strbuf_replace_all(buf, "c", "aa") != 0);
+ fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf));
+ fail_if(strcmp(eina_strbuf_string_get(buf), "baaaab"));
+
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(strbuf_realloc)
+{
+ Eina_Strbuf *buf;
+ char pattern[1024 * 16];
+ unsigned int i;
+ size_t sz;
+
+ for (i = 0; i < sizeof(pattern) - 1; i++)
+ pattern[i] = 'a' + (i % 26);
+ pattern[i] = '\0';
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ sz = 0;
+
+ eina_strbuf_append_length(buf, pattern, 1);
+ fail_if(eina_strbuf_length_get(buf) != sz + 1);
+ fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 1));
+ sz += 1;
+
+ eina_strbuf_append_length(buf, pattern, 32);
+ fail_if(eina_strbuf_length_get(buf) != sz + 32);
+ fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 32));
+ sz += 32;
+
+ eina_strbuf_append_length(buf, pattern, 64);
+ fail_if(eina_strbuf_length_get(buf) != sz + 64);
+ fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 64));
+ sz += 64;
+
+ eina_strbuf_append_length(buf, pattern, 128);
+ fail_if(eina_strbuf_length_get(buf) != sz + 128);
+ fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 128));
+ sz += 128;
+
+ eina_strbuf_append_length(buf, pattern, 4096);
+ fail_if(eina_strbuf_length_get(buf) != sz + 4096);
+ fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 4096));
+ sz += 4096;
+
+ eina_strbuf_append_length(buf, pattern, sizeof(pattern) - 1);
+ fail_if(eina_strbuf_length_get(buf) != sz + sizeof(pattern) - 1);
+ fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, sizeof(pattern) -
+ 1));
+ sz += sizeof(pattern) - 1;
+
+
+ eina_strbuf_remove(buf, 1024, 1024 + 1234);
+ fail_if(eina_strbuf_length_get(buf) != sz - 1234);
+ sz -= 1234;
+
+ eina_strbuf_remove(buf, 0, 0 + 8192);
+ fail_if(eina_strbuf_length_get(buf) != sz - 8192);
+ sz -= 8192;
+
+ eina_strbuf_remove(buf, 0, 0 + 32);
+ fail_if(eina_strbuf_length_get(buf) != sz - 32);
+ sz -= 32;
+
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(strbuf_append_realloc)
+{
+ Eina_Strbuf *buf;
+ const size_t runs = 40960;
+ const char target_pattern[] = "stringstrsstr";
+ const char *str;
+ size_t i, target_pattern_size;
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ for (i = 0; i < runs; i++)
+ {
+ fail_if(!eina_strbuf_append(buf, "string"));
+ fail_if(!eina_strbuf_append_n(buf, "string", 3));
+ fail_if(!eina_strbuf_append_char(buf, 's'));
+ fail_if(!eina_strbuf_append_length(buf, "string", 3));
+ }
+
+ target_pattern_size = strlen(target_pattern);
+ fail_if(eina_strbuf_length_get(buf) != (runs * target_pattern_size));
+
+ str = eina_strbuf_string_get(buf);
+ fail_if(str == NULL);
+ for (i = 0; i < runs; i++, str += target_pattern_size)
+ fail_if(memcmp(str, target_pattern, target_pattern_size));
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(strbuf_prepend_realloc)
+{
+ Eina_Strbuf *buf;
+ const size_t runs = 40960;
+ const char target_pattern[] = "strsstrstring";
+ const char *str;
+ size_t i, target_pattern_size;
+
+ eina_init();
+
+ buf = eina_strbuf_new();
+ fail_if(!buf);
+
+ for (i = 0; i < runs; i++)
+ {
+ fail_if(!eina_strbuf_prepend(buf, "string"));
+ fail_if(!eina_strbuf_prepend_n(buf, "string", 3));
+ fail_if(!eina_strbuf_prepend_char(buf, 's'));
+ fail_if(!eina_strbuf_prepend_length(buf, "string", 3));
+ }
+
+ target_pattern_size = strlen(target_pattern);
+ fail_if(eina_strbuf_length_get(buf) != (runs * target_pattern_size));
+
+ str = eina_strbuf_string_get(buf);
+ fail_if(str == NULL);
+ for (i = 0; i < runs; i++, str += target_pattern_size)
+ fail_if(memcmp(str, target_pattern, target_pattern_size));
+
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_strbuf(TCase *tc)
+{
+ tcase_add_test(tc, strbuf_simple);
+ tcase_add_test(tc, strbuf_remove);
+ tcase_add_test(tc, strbuf_append);
+ tcase_add_test(tc, strbuf_insert);
+ tcase_add_test(tc, strbuf_replace);
+ tcase_add_test(tc, strbuf_realloc);
+ tcase_add_test(tc, strbuf_append_realloc);
+ tcase_add_test(tc, strbuf_prepend_realloc);
+ tcase_add_test(tc, strbuf_manage_simple);
+}
diff --git a/src/tests/eina/eina_test_stringshare.c b/src/tests/eina/eina_test_stringshare.c
new file mode 100644
index 000000000..0d34aec31
--- /dev/null
+++ b/src/tests/eina/eina_test_stringshare.c
@@ -0,0 +1,201 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+#define TEST0 "test/0"
+#define TEST1 "test/1"
+
+START_TEST(eina_stringshare_simple)
+{
+ const char *t0;
+ const char *t1;
+
+ eina_init();
+
+ t0 = eina_stringshare_add(TEST0);
+ t1 = eina_stringshare_add(TEST1);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(strcmp(t0, TEST0) != 0);
+ fail_if(strcmp(t1, TEST1) != 0);
+ fail_if((int)strlen(TEST0) != eina_stringshare_strlen(t0));
+ fail_if((int)strlen(TEST1) != eina_stringshare_strlen(t1));
+
+ t0 = eina_stringshare_ref(t0);
+ fail_if(t0 == NULL);
+ fail_if((int)strlen(TEST0) != eina_stringshare_strlen(t0));
+
+ eina_stringshare_del(t0);
+ eina_stringshare_del(t0);
+ eina_stringshare_del(t1);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_stringshare_small)
+{
+ char buf[4];
+ int i;
+
+ eina_init();
+
+ for (i = 0; i < 3; i++)
+ {
+ const char *t0, *t1;
+ int j;
+
+ for (j = 0; j < i; j++)
+ {
+ char c;
+ for (c = 'a'; c <= 'z'; c++)
+ buf[j] = c;
+ }
+ buf[i] = '\0';
+ t0 = eina_stringshare_add(buf);
+ t1 = eina_stringshare_add(buf);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(t0 != t1);
+ fail_if(strcmp(t0, buf) != 0);
+ fail_if((int)strlen(buf) != eina_stringshare_strlen(t0));
+ fail_if((int)strlen(buf) != eina_stringshare_strlen(t1));
+
+ eina_stringshare_del(t0);
+ eina_stringshare_del(t1);
+ }
+
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_stringshare_test_share)
+{
+ const char *t0;
+ const char *t1;
+
+ eina_init();
+
+ t0 = eina_stringshare_add(TEST0);
+ t1 = eina_stringshare_add(TEST0);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(strcmp(t0, TEST0) != 0);
+ fail_if(strcmp(t1, TEST0) != 0);
+ fail_if(t0 != t1);
+ fail_if((int)strlen(t0) != eina_stringshare_strlen(t0));
+
+ eina_stringshare_del(t0);
+ eina_stringshare_del(t1);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_stringshare_putstuff)
+{
+ const char *tmp;
+ int i;
+
+ eina_init();
+
+ for (i = 10000; i > 0; --i)
+ {
+ char build[64] = "string_";
+
+ eina_convert_xtoa(i, build + 7);
+ tmp = eina_stringshare_add(build);
+ fail_if(tmp != eina_stringshare_add(build));
+ }
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_stringshare_collision)
+{
+ Eina_Array *ea;
+ char buffer[50];
+ int i;
+
+ srand(time(NULL));
+
+ eina_init();
+
+ ea = eina_array_new(256);
+ fail_if(!ea);
+
+ for (i = 0; i < 10000; ++i)
+ {
+ eina_convert_itoa(rand(), buffer);
+ eina_array_push(ea, (void *)eina_stringshare_add(buffer));
+ if (rand() > RAND_MAX / 2)
+ {
+ const char *r = eina_stringshare_add(buffer);
+ fail_if(r == NULL);
+ }
+ }
+
+ for (i = 0; i < 10000; ++i)
+ {
+ const char *r;
+
+ eina_convert_itoa(60000 - i, buffer);
+ eina_array_push(ea, (void *)eina_stringshare_add(buffer));
+ r = eina_stringshare_add(buffer);
+ fail_if(r == NULL);
+ r = eina_stringshare_add(buffer);
+ fail_if(r == NULL);
+ }
+
+ for (i = 0; i < 200; ++i)
+ eina_stringshare_del(eina_array_data_get(ea, i));
+
+ for (i = 0; i < 1000; ++i)
+ eina_stringshare_del(eina_array_pop(ea));
+
+ eina_shutdown();
+
+ eina_array_free(ea);
+}
+END_TEST
+
+void
+eina_test_stringshare(TCase *tc)
+{
+ tcase_add_test(tc, eina_stringshare_simple);
+ tcase_add_test(tc, eina_stringshare_small);
+ tcase_add_test(tc, eina_stringshare_test_share);
+ tcase_add_test(tc, eina_stringshare_collision);
+ tcase_add_test(tc, eina_stringshare_putstuff);
+}
diff --git a/src/tests/eina/eina_test_tiler.c b/src/tests/eina/eina_test_tiler.c
new file mode 100644
index 000000000..f1ef8f068
--- /dev/null
+++ b/src/tests/eina/eina_test_tiler.c
@@ -0,0 +1,184 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2009 Rafael Antognolli
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+struct test_rect
+{
+ unsigned long col, row;
+ int x, y, w, h;
+ Eina_Bool full;
+};
+
+static void
+check_iterator(Eina_Iterator *it, struct test_rect *cur_test)
+{
+ unsigned int i = 0;
+ struct Eina_Tile_Grid_Info *tile;
+
+ EINA_ITERATOR_FOREACH(it, tile) {
+ fail_if(cur_test[i].col != tile->col ||
+ cur_test[i].row != tile->row ||
+ cur_test[i].x != tile->rect.x ||
+ cur_test[i].y != tile->rect.y ||
+ cur_test[i].w != tile->rect.w ||
+ cur_test[i].h != tile->rect.h ||
+ cur_test[i].full != tile->full);
+ i++;
+ }
+
+ fail_if(i == 0);
+}
+
+ START_TEST(eina_test_tile_grid_slicer_iterator)
+{
+ Eina_Iterator *it;
+ struct test_rect *cur_test;
+ struct test_rect test1[] = {{1, 1, 72, 82, 10, 15, 0}};
+ struct test_rect test2[] =
+ {{1, 1, 72, 82, 56, 15, 0},
+ {2, 1, 0, 82, 128, 15, 0},
+ {3, 1, 0, 82, 116, 15, 0}};
+ struct test_rect test3[] =
+ {{1, 1, 72, 82, 10, 46, 0},
+ {1, 2, 72, 0, 10, 128, 0},
+ {1, 3, 72, 0, 10, 126, 0}};
+ struct test_rect test4[] =
+ {{1, 1, 72, 82, 56, 46, 0},
+ {2, 1, 0, 82, 128, 46, 0},
+ {3, 1, 0, 82, 128, 46, 0},
+ {4, 1, 0, 82, 88, 46, 0},
+ {1, 2, 72, 0, 56, 128, 0},
+ {2, 2, 0, 0, 128, 128, 1},
+ {3, 2, 0, 0, 128, 128, 1},
+ {4, 2, 0, 0, 88, 128, 0},
+ {1, 3, 72, 0, 56, 126, 0},
+ {2, 3, 0, 0, 128, 126, 0},
+ {3, 3, 0, 0, 128, 126, 0},
+ {4, 3, 0, 0, 88, 126, 0}};
+ struct test_rect test5[] = {{1, 1, 0, 0, 128, 128, 1}};
+ struct test_rect test6[] = {{1, 1, 0, 0, 1, 1, 0}};
+ struct test_rect test7[] =
+ {{1, 1, 0, 0, 128, 128, 1},
+ {2, 1, 0, 0, 1, 128, 0},
+ {1, 2, 0, 0, 128, 1, 0},
+ {2, 2, 0, 0, 1, 1, 0}};
+
+ eina_init();
+
+ cur_test = test1;
+ it = eina_tile_grid_slicer_iterator_new(200, 210, 10, 15, 128, 128);
+ check_iterator(it, cur_test);
+ eina_iterator_free(it);
+
+ cur_test = test2;
+ it = eina_tile_grid_slicer_iterator_new(200, 210, 300, 15, 128, 128);
+ check_iterator(it, cur_test);
+ eina_iterator_free(it);
+
+ cur_test = test3;
+ it = eina_tile_grid_slicer_iterator_new(200, 210, 10, 300, 128, 128);
+ check_iterator(it, cur_test);
+ eina_iterator_free(it);
+
+ cur_test = test4;
+ it = eina_tile_grid_slicer_iterator_new(200, 210, 400, 300, 128, 128);
+ check_iterator(it, cur_test);
+ eina_iterator_free(it);
+
+ cur_test = test5;
+ it = eina_tile_grid_slicer_iterator_new(128, 128, 128, 128, 128, 128);
+ check_iterator(it, cur_test);
+ eina_iterator_free(it);
+
+ cur_test = test6;
+ it = eina_tile_grid_slicer_iterator_new(128, 128, 1, 1, 128, 128);
+ check_iterator(it, cur_test);
+ eina_iterator_free(it);
+
+ cur_test = test7;
+ it = eina_tile_grid_slicer_iterator_new(128, 128, 129, 129, 128, 128);
+ check_iterator(it, cur_test);
+ eina_iterator_free(it);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_tiler_all)
+{
+ Eina_Tiler *tl;
+ Eina_Iterator *it;
+ Eina_Rectangle *rp;
+ Eina_Rectangle r;
+ int i = 0;
+
+ eina_init();
+
+ tl = eina_tiler_new(640, 480);
+
+ eina_tiler_tile_size_set(tl, 32, 32);
+
+ EINA_RECTANGLE_SET(&r, 50, 50, 20, 20);
+ fail_if(!eina_tiler_rect_add(tl, &r));
+
+ EINA_RECTANGLE_SET(&r, -10, -10, 5, 5);
+ fail_if(eina_tiler_rect_add(tl, &r));
+
+ EINA_RECTANGLE_SET(&r, 40, 40, 20, 20);
+ eina_tiler_rect_del(tl, &r);
+
+ it = eina_tiler_iterator_new(tl);
+ fail_if(!it);
+
+ EINA_ITERATOR_FOREACH(it, rp)
+ {
+ fail_if(rp->w <= 0);
+ fail_if(rp->h <= 0);
+ fail_if(rp->x < 0 || rp->x + rp->w > 640);
+ fail_if(rp->y < 0 || rp->y + rp->h > 480);
+ ++i;
+ }
+
+ fail_if(eina_iterator_container_get(it) != tl);
+
+ eina_iterator_free(it);
+
+ fail_if(i == 0);
+
+ eina_tiler_clear(tl);
+
+ eina_tiler_free(tl);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_tiler(TCase *tc)
+{
+ tcase_add_test(tc, eina_test_tile_grid_slicer_iterator);
+ tcase_add_test(tc, eina_test_tiler_all);
+}
diff --git a/src/tests/eina/eina_test_ustr.c b/src/tests/eina/eina_test_ustr.c
new file mode 100644
index 000000000..75126cc6f
--- /dev/null
+++ b/src/tests/eina/eina_test_ustr.c
@@ -0,0 +1,593 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2010 Brett Nash
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+#ifdef EINA_SAFETY_CHECKS
+struct log_ctx {
+ const char *msg;
+ const char *fnc;
+ Eina_Bool did;
+};
+
+/* tests should not output on success, just uncomment this for debugging */
+//#define SHOW_LOG 1
+
+static void
+_eina_test_safety_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
+{
+ struct log_ctx *ctx = data;
+ va_list cp_args;
+ const char *str;
+
+ va_copy(cp_args, args);
+ str = va_arg(cp_args, const char *);
+ va_end(cp_args);
+
+ ck_assert_int_eq(level, EINA_LOG_LEVEL_ERR);
+ ck_assert_str_eq(fmt, "%s");
+ ck_assert_str_eq(ctx->msg, str);
+ ck_assert_str_eq(ctx->fnc, fnc);
+ ctx->did = EINA_TRUE;
+
+#ifdef SHOW_LOG
+ eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
+#else
+ (void)d;
+ (void)file;
+ (void)line;
+#endif
+}
+#endif
+
+static const Eina_Unicode STR1[] = {'P', 'a', 'n', 't', 's',' ', 'O', 'n', 0};
+static const Eina_Unicode STR2[] = {'P', 'a', 'n', 't', 's',' ', 'O', 'f', 'f', 0};
+static const Eina_Unicode STR3[] = {'P', 'a', 'n', 't', 's',' ', 'O', 'n', 0};
+static const Eina_Unicode STR4[] = {'A', 0};
+static const Eina_Unicode EMPTYSTR[] = {0};
+
+START_TEST(eina_unicode_strcmp_test)
+{
+ eina_init();
+
+ /* 1 & 2 */
+ fail_if(eina_unicode_strcmp(STR1,STR2) == 0);
+ fail_if(eina_unicode_strcmp(STR1,STR2) < 1);
+
+ /* 1 & 3 */
+ fail_if(eina_unicode_strcmp(STR1, STR3) != 0);
+
+ /* 1 & 4 */
+ fail_if(eina_unicode_strcmp(STR1, STR4) == 0);
+ fail_if(eina_unicode_strcmp(STR1, STR4) > 1);
+
+ /* 1 & empty */
+ fail_if(eina_unicode_strcmp(STR1, EMPTYSTR) < 1);
+
+ /* Self tests */
+ fail_if(eina_unicode_strcmp(STR1, STR1) != 0);
+ fail_if(eina_unicode_strcmp(STR2, STR2) != 0);
+ fail_if(eina_unicode_strcmp(STR3, STR3) != 0);
+ fail_if(eina_unicode_strcmp(STR4, STR4) != 0);
+ fail_if(eina_unicode_strcmp(EMPTYSTR, EMPTYSTR) != 0);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_unicode_strcpy_test)
+{
+ Eina_Unicode buf[10] = { 0 };
+ Eina_Unicode *rv;
+
+ eina_init();
+
+ rv = eina_unicode_strcpy(buf,STR1);
+ fail_if(rv != buf);
+ fail_if(eina_unicode_strcmp(buf,STR1) != 0);
+
+ rv = eina_unicode_strcpy(buf,STR2);
+ fail_if(rv != buf);
+ fail_if(eina_unicode_strcmp(buf,STR2) != 0);
+
+ /* Now a shorter string */
+ rv = eina_unicode_strcpy(buf,STR2);
+ fail_if(rv != buf);
+ fail_if(eina_unicode_strcmp(buf,STR2) != 0);
+
+ /* Really short string */
+ rv = eina_unicode_strcpy(buf,STR4);
+ fail_if(rv != buf);
+ fail_if(eina_unicode_strcmp(buf,STR4) != 0);
+ fail_if(buf[2] != 'n'); /* check old buf is there */
+
+ buf[1] = '7';
+ rv = eina_unicode_strcpy(buf,EMPTYSTR);
+ fail_if(rv != buf);
+ fail_if(buf[0] != 0);
+ fail_if(buf[1] != '7');
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_unicode_strncpy_test)
+{
+ Eina_Unicode buf[10] = { 0 };
+ Eina_Unicode *rv;
+
+ eina_init();
+
+ rv = eina_unicode_strncpy(buf,STR1,9);
+ fail_if(rv != buf);
+ fail_if(eina_unicode_strcmp(buf,STR1) != 0);
+
+ buf[1] = '7';
+ rv = eina_unicode_strncpy(buf,STR1,1);
+ fail_if(rv != buf);
+ fail_if(buf[1] != '7');
+ fail_if(buf[0] != STR1[0]);
+
+ buf[9] = '7';
+ rv = eina_unicode_strncpy(buf, STR4, 10);
+ fail_if(rv != buf);
+ fail_if(eina_unicode_strcmp(buf,STR4) != 0);
+ fail_if(buf[9] != 0);
+
+ buf[0] = '7';
+ rv = eina_unicode_strncpy(buf, STR1, 0);
+ fail_if(buf[0] != '7');
+
+#ifdef EINA_SAFETY_CHECKS
+ {
+ struct log_ctx ctx;
+
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+ /* may segfault */
+ buf[0] = '7';
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_unicode_strncpy",
+ "safety check failed: source == NULL");
+ rv = eina_unicode_strncpy(buf, NULL, 0);
+ fail_if(buf[0] != '7');
+ fail_unless(ctx.did);
+
+ /* Hopefully won't segfault */
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_unicode_strncpy",
+ "safety check failed: dest == NULL");
+ rv = eina_unicode_strncpy(NULL, STR1, 0);
+ fail_if(rv != NULL);
+ fail_unless(ctx.did);
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+#undef TEST_MAGIC_SAFETY
+ }
+#endif
+
+ eina_shutdown();
+}
+END_TEST
+
+
+
+START_TEST(eina_ustr_strlen_test)
+{
+
+ eina_init();
+
+ fail_if(eina_unicode_strlen(STR1) != 8);
+ fail_if(eina_unicode_strlen(STR2) != 9);
+ fail_if(eina_unicode_strlen(STR3) != 8);
+ fail_if(eina_unicode_strlen(STR4) != 1);
+ fail_if(eina_unicode_strlen(EMPTYSTR) != 0);
+
+#ifdef EINA_SAFETY_CHECKS
+ {
+ struct log_ctx ctx;
+
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_unicode_strlen",
+ "safety check failed: ustr == NULL");
+ fail_if(eina_unicode_strlen(NULL));
+ fail_unless(ctx.did);
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+#undef TEST_MAGIC_SAFETY
+ }
+#endif
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_unicode_strnlen_test)
+{
+ eina_init();
+
+ /* Strlen style tests*/
+ fail_if(eina_unicode_strnlen(STR1,10) != 8);
+ fail_if(eina_unicode_strnlen(STR2,10) != 9);
+ fail_if(eina_unicode_strnlen(STR3,10) != 8);
+ fail_if(eina_unicode_strnlen(STR4,10) != 1);
+ fail_if(eina_unicode_strnlen(EMPTYSTR,10) != 0);
+
+ /* Too short tests */
+ fail_if(eina_unicode_strnlen(STR1,3) != 3);
+ fail_if(eina_unicode_strnlen(STR2,3) != 3);
+ fail_if(eina_unicode_strnlen(STR3,3) != 3);
+ fail_if(eina_unicode_strnlen(EMPTYSTR,1) != 0);
+
+#ifdef EINA_SAFETY_CHECKS
+ {
+ struct log_ctx ctx;
+
+#define TEST_MAGIC_SAFETY(fn, _msg) \
+ ctx.msg = _msg; \
+ ctx.fnc = fn; \
+ ctx.did = EINA_FALSE
+
+ eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
+
+#ifdef SHOW_LOG
+ fprintf(stderr, "you should have a safety check failure below:\n");
+#endif
+ TEST_MAGIC_SAFETY("eina_unicode_strnlen",
+ "safety check failed: ustr == NULL");
+ fail_if(eina_unicode_strnlen(NULL,0) != 0);
+ fail_unless(ctx.did);
+
+ eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
+#undef TEST_MAGIC_SAFETY
+ }
+#endif
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_unicode_strdup_test)
+{
+ Eina_Unicode *buf;
+
+ eina_init();
+
+ buf = eina_unicode_strdup(STR1);
+ fail_if(!buf);
+ fail_if(eina_unicode_strlen(buf) != eina_unicode_strlen(STR1));
+ fail_if(eina_unicode_strcmp(buf, STR1));
+ free(buf);
+
+ buf = eina_unicode_strdup(EMPTYSTR);
+ fail_if(!buf);
+ fail_if(buf[0] != 0);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_unicode_strstr_test)
+{
+ Eina_Unicode *buf;
+ Eina_Unicode on[] = { 'O', 'n', 0 };
+
+ eina_init();
+
+ buf = eina_unicode_strstr(STR1,on);
+ fail_if(!buf);
+ fail_if(buf != STR1 + 6);
+ fail_if(eina_unicode_strcmp(buf,on) != 0);
+
+ buf = eina_unicode_strstr(STR2,on);
+ fail_if(buf);
+
+ buf = eina_unicode_strstr(EMPTYSTR, on);
+ fail_if(buf);
+
+ buf = eina_unicode_strstr(STR1, EMPTYSTR);
+ fail_if(!buf);
+ fail_if(buf != STR1);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_unicode_utf8)
+{
+ int ind;
+ unsigned char ch;
+ eina_init();
+
+ /* Valid utf-8 cases */
+ /* First possible sequence of a certain length */
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\x00", &ind) != 0x00) ||
+ (ind != 0));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\x01", &ind) != 0x01) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xC2\x80", &ind) != 0x80) ||
+ (ind != 2));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xE0\xA0\x80", &ind) != 0x800) ||
+ (ind != 3));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF0\x90\x80\x80", &ind) != 0x10000) ||
+ (ind != 4));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF8\x88\x80\x80\x80", &ind) != 0x200000) || (ind != 5));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xFC\x84\x80\x80\x80\x80", &ind) != 0x4000000) || (ind != 6));
+
+ /* Last possible sequence of a certain length */
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\x7F", &ind) != 0x7F) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xDF\xBF", &ind) != 0x7FF) ||
+ (ind != 2));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xEF\xBF\xBF", &ind) != 0xFFFF) ||
+ (ind != 3));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF7\xBF\xBF\xBF", &ind) != 0x1FFFFF) ||
+ (ind != 4));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xFB\xBF\xBF\xBF\xBF", &ind) != 0x3FFFFFF) || (ind != 5));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xFD\xBF\xBF\xBF\xBF\xBF", &ind) != 0x7FFFFFFF) || (ind != 6));
+
+ /* Other boundary conditions */
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xED\x9F\xBF", &ind) != 0xD7FF) ||
+ (ind != 3));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xEE\x80\x80", &ind) != 0xE000) ||
+ (ind != 3));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xEF\xBF\xBD", &ind) != 0xFFFD) ||
+ (ind != 3));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF4\x8F\xBF\xBF", &ind) != 0x10FFFF) ||
+ (ind != 4));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF4\x90\x80\x80", &ind) != 0x110000) ||
+ (ind != 4));
+
+ /* Error cases */
+ /* Standalone continuation bytes */
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\x80", &ind) != 0xDC80) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xBF", &ind) != 0xDCBF) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\x80\xBF", &ind) != 0xDC80) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xBF\x80", &ind) != 0xDCBF) ||
+ (ind != 1));
+ /* All possible continuation bytes */
+ for (ch = 0x80 ; ch <= 0xBF ; ch++)
+ {
+ char buf[] = {ch, 0};
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next(buf, &ind) != (0xDC00 | ch)) ||
+ (ind != 1));
+ }
+
+ /* Isolated starting sequences */
+#define _FIRST_SEQUENCES(start, end) \
+ do \
+ { \
+ int i; \
+ char *buf = alloca(((end - start + 1) * 2) + 1); \
+ for (i = 0, ch = start ; ch <= end ; i++, ch++) \
+ { \
+ buf[i * 2] = ch; \
+ buf[(i * 2) + 1] = ' '; \
+ } \
+ ind = 0; \
+ for (i = 0, ch = start ; ch <= end ; ch++) \
+ { \
+ fail_if((eina_unicode_utf8_get_next(buf, &ind) != (0xDC00 | ch)) || \
+ (ind != ++i)); \
+ fail_if((eina_unicode_utf8_get_next(buf, &ind) != 0x20) || \
+ (ind != ++i)); \
+ } \
+ } \
+ while (0)
+ /* all first bytes of 2-byte sequences separated by spaces. */
+ _FIRST_SEQUENCES(0xC0, 0xDF);
+ /* all first bytes of 3-byte sequences separated by spaces. */
+ _FIRST_SEQUENCES(0xE0, 0xEF);
+ /* all first bytes of 4-byte sequences separated by spaces. */
+ _FIRST_SEQUENCES(0xF0, 0xF7);
+ /* all first bytes of 5-byte sequences separated by spaces. */
+ _FIRST_SEQUENCES(0xF8, 0xFB);
+ /* all first bytes of 6-byte sequences separated by spaces. */
+ _FIRST_SEQUENCES(0xFC, 0xFD);
+
+ /* Incomplete sequences first means the first utf8 char, len means
+ * the correct length */
+#define _INCOMPLETE_SEQUENCES(first, conti, len) \
+ do \
+ { \
+ int i, j; \
+ char *buf = alloca(len + 1); \
+ i = 0; \
+ buf[i++] = first; \
+ for ( ; i < len ; i++) \
+ { \
+ Eina_Unicode val; \
+ for (j = 1 ; j < i ; j++) \
+ { \
+ buf[j] = conti; \
+ } \
+ buf[j] = 0; \
+ ind = 0; \
+ fail_if( \
+ (eina_unicode_utf8_get_next(buf, &ind) != (0xDC00 | first))); \
+ while ((val = eina_unicode_utf8_get_next(buf, &ind))) \
+ { \
+ fail_if(val != (0xDC00 | conti)); \
+ } \
+ fail_if(ind != i); \
+ } \
+ } \
+ while (0)
+
+ /* Sequences with missing continuation */
+ _INCOMPLETE_SEQUENCES(0xC0, 0x81, 2);
+ _INCOMPLETE_SEQUENCES(0xDF, 0xBF, 2);
+ _INCOMPLETE_SEQUENCES(0xE0, 0x81, 3);
+ _INCOMPLETE_SEQUENCES(0xEF, 0xBF, 3);
+ _INCOMPLETE_SEQUENCES(0xF0, 0x81, 4);
+ _INCOMPLETE_SEQUENCES(0xF7, 0xBF, 4);
+ _INCOMPLETE_SEQUENCES(0xF8, 0x81, 5);
+ _INCOMPLETE_SEQUENCES(0xFB, 0xBF, 5);
+ _INCOMPLETE_SEQUENCES(0xFC, 0x81, 6);
+ _INCOMPLETE_SEQUENCES(0xFD, 0xBF, 6);
+
+ /* Impossible bytes */
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xFE", &ind) != 0xDCFE) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xFF", &ind) != 0xDCFF) ||
+ (ind != 1));
+
+ /* Overlong sequences */
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xC0\xAF", &ind) != 0xDCC0) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xE0\x80\xAF", &ind) != 0xDCE0) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF0\x80\x80\xAF", &ind) != 0xDCF0) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF8\x80\x80\x80\xAF", &ind) != 0xDCF8) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xFC\x80\x80\x80\x80\xAF", &ind) != 0xDCFC) ||
+ (ind != 1));
+
+ /* Maximum overlong sequences */
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xC1\xBF", &ind) != 0xDCC1) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xE0\x9F\xBF", &ind) != 0xDCE0) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF0\x8F\xBF\xBF", &ind) != 0xDCF0) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xF8\x87\xBF\xBF\xBF", &ind) != 0xDCF8) ||
+ (ind != 1));
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_next("\xFC\x83\xBF\xBF\xBF\xBF", &ind) != 0xDCFC) ||
+ (ind != 1));
+ /* Add some more error cases here */
+
+ /* Just to cover prev/len. General utf-8 parsing was covered above */
+ fail_if(eina_unicode_utf8_get_len("\xF4\x90\x80\x80\xF4\x8F\xBF\xBF") != 2);
+ ind = 0;
+ fail_if((eina_unicode_utf8_get_prev("\xED\x9F\xBF", &ind) != 0xD7FF) ||
+ (ind != 0));
+ ind = 3;
+ fail_if((eina_unicode_utf8_get_prev("\xED\x9F\xBF", &ind) != 0x00) ||
+ (ind != 0));
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_unicode_utf8_conversion)
+{
+ Eina_Unicode uni_in[] = {0x5D0, 0xFDF6, 0xDC80, 0x1F459, 0x3FFFFFF,
+ 0x7FFFFFFF, 'a', 'b', 'c', 0};
+ Eina_Unicode *uni_out;
+ char c_in[] = "\xD7\x90""\xEF\xB7\xB6""\x80""\xF0\x9F\x91\x99"
+ "\xFB\xBF\xBF\xBF\xBF""\xFD\xBF\xBF\xBF\xBF\xBF""abc";
+ char *c_out;
+ int len;
+
+ eina_init();
+
+ uni_out = eina_unicode_utf8_to_unicode(c_in, &len);
+ fail_if((len != 9) || eina_unicode_strcmp(uni_in, uni_out));
+ free(uni_out);
+
+ c_out = eina_unicode_unicode_to_utf8(uni_in, &len);
+ fail_if((len != 24) || strcmp(c_in, c_out));
+ free(c_out);
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_ustr(TCase *tc)
+{
+ printf("ustr test\n");
+ tcase_add_test(tc,eina_unicode_strcmp_test);
+ tcase_add_test(tc,eina_unicode_strcpy_test);
+ tcase_add_test(tc,eina_unicode_strncpy_test);
+ tcase_add_test(tc,eina_ustr_strlen_test);
+ tcase_add_test(tc,eina_unicode_strnlen_test);
+ tcase_add_test(tc,eina_unicode_strdup_test);
+ tcase_add_test(tc,eina_unicode_strstr_test);
+ tcase_add_test(tc,eina_unicode_utf8);
+ tcase_add_test(tc,eina_unicode_utf8_conversion);
+
+}
+
diff --git a/src/tests/eina/eina_test_ustringshare.c b/src/tests/eina/eina_test_ustringshare.c
new file mode 100644
index 000000000..1b1ffb262
--- /dev/null
+++ b/src/tests/eina/eina_test_ustringshare.c
@@ -0,0 +1,119 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric Bail
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+static const Eina_Unicode TEST0[] = {'t', 'e', 's', 't', '/', '0', 0};
+static const Eina_Unicode TEST1[] = {'t', 'e', 's', 't', '/', '1', 0};
+
+START_TEST(eina_ustringshare_simple)
+{
+ const Eina_Unicode *t0;
+ const Eina_Unicode *t1;
+
+ eina_init();
+
+ t0 = eina_ustringshare_add(TEST0);
+ t1 = eina_ustringshare_add(TEST1);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(eina_unicode_strcmp(t0, TEST0) != 0);
+ fail_if(eina_unicode_strcmp(t1, TEST1) != 0);
+ fail_if((int)eina_unicode_strlen(TEST0) != eina_ustringshare_strlen(t0));
+ fail_if((int)eina_unicode_strlen(TEST1) != eina_ustringshare_strlen(t1));
+
+ t0 = eina_ustringshare_ref(t0);
+ fail_if(t0 == NULL);
+ fail_if((int)strlen((char*)TEST0) != eina_stringshare_strlen((const char*)t0));
+
+ eina_ustringshare_del(t0);
+ eina_ustringshare_del(t0);
+ eina_ustringshare_del(t1);
+
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_ustringshare_test_share)
+{
+ const Eina_Unicode *t0;
+ const Eina_Unicode *t1;
+
+ eina_init();
+
+ t0 = eina_ustringshare_add(TEST0);
+ t1 = eina_ustringshare_add(TEST0);
+
+ fail_if(t0 == NULL);
+ fail_if(t1 == NULL);
+ fail_if(eina_unicode_strcmp(t0, TEST0) != 0);
+ fail_if(eina_unicode_strcmp(t1, TEST0) != 0);
+ fail_if(t0 != t1);
+ fail_if((int)eina_unicode_strlen(TEST0) != eina_ustringshare_strlen(t0));
+ fail_if((int)eina_unicode_strlen(TEST0) != eina_ustringshare_strlen(t1));
+
+ eina_ustringshare_del(t0);
+ eina_ustringshare_del(t1);
+
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_ustringshare_putstuff)
+{
+ const Eina_Unicode *tmp;
+ int i;
+
+ eina_init();
+
+ for (i = 10000; i > 0; --i)
+ {
+ Eina_Unicode string_[] = {'s', 't', 'r', 'i', 'n', 'g', '_', 0};
+ Eina_Unicode build[64];
+ eina_unicode_strcpy(build, string_);
+
+ build[7] = i;
+ build[8] = 0;
+ tmp = eina_ustringshare_add(build);
+ fail_if(tmp != eina_ustringshare_add(build));
+ fail_if((int)eina_unicode_strlen(build) != eina_ustringshare_strlen(tmp));
+ }
+
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_ustringshare(TCase *tc)
+{
+ tcase_add_test(tc, eina_ustringshare_simple);
+ tcase_add_test(tc, eina_ustringshare_test_share);
+ tcase_add_test(tc, eina_ustringshare_putstuff);
+}
diff --git a/src/tests/eina/eina_test_value.c b/src/tests/eina/eina_test_value.c
new file mode 100644
index 000000000..68ef5ec0c
--- /dev/null
+++ b/src/tests/eina/eina_test_value.c
@@ -0,0 +1,1877 @@
+/* EINA - EFL data type library
+ * Copyright (C) 2012 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+#define FP_ERR (0.0000001)
+#define CHECK_FP(a, b) ((a - b) < FP_ERR)
+
+START_TEST(eina_value_test_simple)
+{
+ Eina_Value *value;
+ char c;
+ short s;
+ int i;
+ long l;
+ int64_t i64;
+ unsigned char uc;
+ unsigned short us;
+ unsigned int ui;
+ unsigned long ul;
+ uint64_t u64;
+ float f;
+ double d;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_CHAR);
+ fail_unless(value != NULL);
+ fail_unless(eina_value_set(value, 'x'));
+ fail_unless(eina_value_get(value, &c));
+ fail_unless(c == 'x');
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_SHORT));
+ fail_unless(eina_value_set(value, 300));
+ fail_unless(eina_value_get(value, &s));
+ fail_unless(s == 300);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(value, -12345));
+ fail_unless(eina_value_get(value, &i));
+ fail_unless(i == -12345);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_LONG));
+ fail_unless(eina_value_set(value, 0xb33f));
+ fail_unless(eina_value_get(value, &l));
+ fail_unless(l == 0xb33f);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT64));
+ fail_unless(eina_value_set(value, 0x0011223344556677));
+ fail_unless(eina_value_get(value, &i64));
+ fail_unless(i64 == 0x0011223344556677);
+ eina_value_flush(value);
+
+ /* unsigned: */
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UCHAR));
+ fail_unless(eina_value_set(value, 200));
+ fail_unless(eina_value_get(value, &uc));
+ fail_unless(uc == 200);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_USHORT));
+ fail_unless(eina_value_set(value, 65535));
+ fail_unless(eina_value_get(value, &us));
+ fail_unless(us == 65535);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT));
+ fail_unless(eina_value_set(value, 4000000000U));
+ fail_unless(eina_value_get(value, &ui));
+ fail_unless(ui == 4000000000U);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_ULONG));
+ fail_unless(eina_value_set(value, 3000000001UL));
+ fail_unless(eina_value_get(value, &ul));
+ fail_unless(ul == 3000000001UL);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT64));
+ fail_unless(eina_value_set(value, 0x1122334455667788));
+ fail_unless(eina_value_get(value, &u64));
+ fail_unless(u64 == 0x1122334455667788);
+ eina_value_flush(value);
+
+ /* floating point */
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_FLOAT));
+ fail_unless(eina_value_set(value, 0.1234));
+ fail_unless(eina_value_get(value, &f));
+ fail_unless(CHECK_FP(0.1234, f));
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_DOUBLE));
+ fail_unless(eina_value_set(value, 34567.8));
+ fail_unless(eina_value_get(value, &d));
+ fail_unless(CHECK_FP(34567.8, d));
+ eina_value_flush(value);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_compare)
+{
+ Eina_Value *a, *b;
+
+ eina_init();
+
+ a = eina_value_new(EINA_VALUE_TYPE_CHAR);
+ fail_unless(a != NULL);
+ b = eina_value_new(EINA_VALUE_TYPE_CHAR);
+ fail_unless(b != NULL);
+
+ fail_unless(eina_value_set(a, 123));
+ fail_unless(eina_value_set(b, 123));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, -10));
+ fail_unless(eina_value_set(b, 123));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 123));
+ fail_unless(eina_value_set(b, 10));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_SHORT));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_SHORT));
+ fail_unless(eina_value_set(a, 1230));
+ fail_unless(eina_value_set(b, 1230));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, -100));
+ fail_unless(eina_value_set(b, 1230));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 1230));
+ fail_unless(eina_value_set(b, -100));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(a, 300000));
+ fail_unless(eina_value_set(b, 300000));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, -100));
+ fail_unless(eina_value_set(b, 300000));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 300000));
+ fail_unless(eina_value_set(b, -100));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_LONG));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_LONG));
+ fail_unless(eina_value_set(a, 300000L));
+ fail_unless(eina_value_set(b, 300000L));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, -100L));
+ fail_unless(eina_value_set(b, 300000L));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 300000L));
+ fail_unless(eina_value_set(b, -100L));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_INT64));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_INT64));
+ fail_unless(eina_value_set(a, (int64_t)800000));
+ fail_unless(eina_value_set(b, (int64_t)800000));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, (int64_t)-100));
+ fail_unless(eina_value_set(b, (int64_t)8000000));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, (int64_t)8000000));
+ fail_unless(eina_value_set(b, (int64_t)-100));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_UCHAR));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_UCHAR));
+ fail_unless(eina_value_set(a, 123));
+ fail_unless(eina_value_set(b, 123));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, 10));
+ fail_unless(eina_value_set(b, 123));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 123));
+ fail_unless(eina_value_set(b, 10));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_USHORT));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_USHORT));
+ fail_unless(eina_value_set(a, 1230));
+ fail_unless(eina_value_set(b, 1230));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, 100));
+ fail_unless(eina_value_set(b, 1230));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 1230));
+ fail_unless(eina_value_set(b, 100));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_UINT));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_UINT));
+ fail_unless(eina_value_set(a, 300000));
+ fail_unless(eina_value_set(b, 300000));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, 100));
+ fail_unless(eina_value_set(b, 300000));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 300000));
+ fail_unless(eina_value_set(b, 100));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_ULONG));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_ULONG));
+ fail_unless(eina_value_set(a, 300000UL));
+ fail_unless(eina_value_set(b, 300000UL));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, 100UL));
+ fail_unless(eina_value_set(b, 300000UL));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, 300000UL));
+ fail_unless(eina_value_set(b, 100UL));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_UINT64));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_UINT64));
+ fail_unless(eina_value_set(a, (uint64_t)8000000));
+ fail_unless(eina_value_set(b, (uint64_t)8000000));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, (uint64_t)100));
+ fail_unless(eina_value_set(b, (uint64_t)8000000));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, (uint64_t)8000000));
+ fail_unless(eina_value_set(b, (uint64_t)100));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_STRING));
+ fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_STRING));
+ fail_unless(eina_value_set(a, "aaa"));
+ fail_unless(eina_value_set(b, "aaa"));
+ fail_unless(eina_value_compare(a, b) == 0);
+ fail_unless(eina_value_set(a, "abc"));
+ fail_unless(eina_value_set(b, "acd"));
+ fail_unless(eina_value_compare(a, b) < 0);
+ fail_unless(eina_value_set(a, "acd"));
+ fail_unless(eina_value_set(b, "abc"));
+ fail_unless(eina_value_compare(a, b) > 0);
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_array_setup(a, EINA_VALUE_TYPE_CHAR, 0));
+ fail_unless(eina_value_array_setup(b, EINA_VALUE_TYPE_CHAR, 0));
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ fail_unless(eina_value_array_append(a, 1));
+ fail_unless(eina_value_array_append(a, 2));
+ fail_unless(eina_value_array_append(a, 3));
+
+ fail_unless(eina_value_array_append(b, 1));
+ fail_unless(eina_value_array_append(b, 2));
+ fail_unless(eina_value_array_append(b, 3));
+
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ fail_unless(eina_value_array_set(a, 0, 0));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_array_set(a, 0, 10));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ fail_unless(eina_value_array_set(a, 0, 1));
+
+ fail_unless(eina_value_array_set(b, 0, 0));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ fail_unless(eina_value_array_set(b, 0, 10));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_array_set(b, 0, 1));
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ /* bigger arrays are greater */
+ fail_unless(eina_value_array_append(b, 0));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_array_append(a, 0));
+ fail_unless(eina_value_array_append(a, 0));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ /* bigger arrays are greater, unless an element says otherwise */
+ fail_unless(eina_value_array_set(b, 0, 10));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_list_setup(a, EINA_VALUE_TYPE_CHAR));
+ fail_unless(eina_value_list_setup(b, EINA_VALUE_TYPE_CHAR));
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ fail_unless(eina_value_list_append(a, 1));
+ fail_unless(eina_value_list_append(a, 2));
+ fail_unless(eina_value_list_append(a, 3));
+
+ fail_unless(eina_value_list_append(b, 1));
+ fail_unless(eina_value_list_append(b, 2));
+ fail_unless(eina_value_list_append(b, 3));
+
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ fail_unless(eina_value_list_set(a, 0, 0));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_list_set(a, 0, 10));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ fail_unless(eina_value_list_set(a, 0, 1));
+
+ fail_unless(eina_value_list_set(b, 0, 0));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ fail_unless(eina_value_list_set(b, 0, 10));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_list_set(b, 0, 1));
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ /* bigger lists are greater */
+ fail_unless(eina_value_list_append(b, 0));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_list_append(a, 0));
+ fail_unless(eina_value_list_append(a, 0));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ /* bigger lists are greater, unless an element says otherwise */
+ fail_unless(eina_value_list_set(b, 0, 10));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ eina_value_flush(a);
+ eina_value_flush(b);
+
+ fail_unless(eina_value_hash_setup(a, EINA_VALUE_TYPE_CHAR, 0));
+ fail_unless(eina_value_hash_setup(b, EINA_VALUE_TYPE_CHAR, 0));
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ fail_unless(eina_value_hash_set(a, "abc", 1));
+ fail_unless(eina_value_hash_set(a, "xyz", 2));
+ fail_unless(eina_value_hash_set(a, "hello", 3));
+
+ fail_unless(eina_value_hash_set(b, "abc", 1));
+ fail_unless(eina_value_hash_set(b, "xyz", 2));
+ fail_unless(eina_value_hash_set(b, "hello", 3));
+
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ fail_unless(eina_value_hash_set(a, "abc", 0));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_hash_set(a, "abc", 10));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ fail_unless(eina_value_hash_set(a, "abc", 1));
+
+ fail_unless(eina_value_hash_set(b, "abc", 0));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ fail_unless(eina_value_hash_set(b, "abc", 10));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_hash_set(b, "abc", 1));
+ fail_unless(eina_value_compare(a, b) == 0);
+
+ /* bigger hashs are greater */
+ fail_unless(eina_value_hash_set(b,"newkey", 0));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ fail_unless(eina_value_hash_set(a, "newkey", 0));
+ fail_unless(eina_value_hash_set(a, "onemorenewkey", 0));
+ fail_unless(eina_value_compare(a, b) > 0);
+
+ /* bigger hashs are greater, unless an element says otherwise */
+ fail_unless(eina_value_hash_set(b, "abc", 10));
+ fail_unless(eina_value_compare(a, b) < 0);
+
+ eina_value_free(a);
+ eina_value_free(b);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_string)
+{
+ Eina_Value *value;
+ const char *s;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_STRING);
+ fail_unless(value != NULL);
+ fail_unless(eina_value_set(value, "hello world!"));
+ fail_unless(eina_value_get(value, &s));
+ fail_unless(strcmp(s, "hello world!") == 0);
+
+ fail_unless(eina_value_set(value, "eina-value"));
+ fail_unless(eina_value_get(value, &s));
+ fail_unless(strcmp(s, "eina-value") == 0);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING));
+
+ fail_unless(eina_value_set(value, "profusion"));
+ fail_unless(eina_value_get(value, &s));
+ fail_unless(strcmp(s, "profusion") == 0);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_pvariant)
+{
+ Eina_Value *value;
+ char c, in_c;
+ short s, in_s;
+ int i, in_i;
+ long l, in_l;
+ int64_t i64, in_i64;
+ unsigned char uc, in_uc;
+ unsigned short us, in_us;
+ unsigned int ui, in_ui;
+ unsigned long ul, in_ul;
+ uint64_t u64, in_u64;
+ float f, in_f;
+ double d, in_d;
+ const char *str, *in_str;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_CHAR);
+ fail_unless(value != NULL);
+ in_c = 'x';
+ fail_unless(eina_value_pset(value, &in_c));
+ fail_unless(eina_value_pget(value, &c));
+ fail_unless(c == 'x');
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_SHORT));
+ in_s = 300;
+ fail_unless(eina_value_pset(value, &in_s));
+ fail_unless(eina_value_pget(value, &s));
+ fail_unless(s == 300);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT));
+ in_i = -12345;
+ fail_unless(eina_value_pset(value, &in_i));
+ fail_unless(eina_value_pget(value, &i));
+ fail_unless(i == -12345);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_LONG));
+ in_l = 0xb33f;
+ fail_unless(eina_value_pset(value, &in_l));
+ fail_unless(eina_value_pget(value, &l));
+ fail_unless(l == 0xb33f);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT64));
+ in_i64 = 0x0011223344556677;
+ fail_unless(eina_value_pset(value, &in_i64));
+ fail_unless(eina_value_pget(value, &i64));
+ fail_unless(i64 == 0x0011223344556677);
+ eina_value_flush(value);
+
+ /* unsigned: */
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UCHAR));
+ in_uc = 200;
+ fail_unless(eina_value_pset(value, &in_uc));
+ fail_unless(eina_value_pget(value, &uc));
+ fail_unless(uc == 200);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_USHORT));
+ in_us = 65535;
+ fail_unless(eina_value_pset(value, &in_us));
+ fail_unless(eina_value_pget(value, &us));
+ fail_unless(us == 65535);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT));
+ in_ui = 4000000000U;
+ fail_unless(eina_value_pset(value, &in_ui));
+ fail_unless(eina_value_pget(value, &ui));
+ fail_unless(ui == 4000000000U);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_ULONG));
+ in_ul = 3000000001UL;
+ fail_unless(eina_value_pset(value, &in_ul));
+ fail_unless(eina_value_pget(value, &ul));
+ fail_unless(ul == 3000000001UL);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT64));
+ in_u64 = 0x1122334455667788;
+ fail_unless(eina_value_pset(value, &in_u64));
+ fail_unless(eina_value_pget(value, &u64));
+ fail_unless(u64 == 0x1122334455667788);
+ eina_value_flush(value);
+
+ /* floating point */
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_FLOAT));
+ in_f = 0.1234;
+ fail_unless(eina_value_pset(value, &in_f));
+ fail_unless(eina_value_pget(value, &f));
+ fail_unless(CHECK_FP(0.1234, f));
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_DOUBLE));
+ in_d = 34567.8;
+ fail_unless(eina_value_pset(value, &in_d));
+ fail_unless(eina_value_pget(value, &d));
+ fail_unless(CHECK_FP(34567.8, d));
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING));
+ in_str = "hello world!";
+ fail_unless(eina_value_pset(value, &in_str));
+ fail_unless(eina_value_pget(value, &str));
+ fail_unless(strcmp(str, "hello world!") == 0);
+
+ in_str = "eina-value";
+ fail_unless(eina_value_pset(value, &in_str));
+ fail_unless(eina_value_pget(value, &str));
+ fail_unless(strcmp(str, "eina-value") == 0);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING));
+
+ in_str = "profusion";
+ fail_unless(eina_value_pset(value, &in_str));
+ fail_unless(eina_value_pget(value, &str));
+ fail_unless(strcmp(str, "profusion") == 0);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_to_string)
+{
+ Eina_Value *value;
+ char c, in_c;
+ short s, in_s;
+ int i, in_i;
+ long l, in_l;
+ int64_t i64, in_i64;
+ unsigned char uc, in_uc;
+ unsigned short us, in_us;
+ unsigned int ui, in_ui;
+ unsigned long ul, in_ul;
+ uint64_t u64, in_u64;
+ float f, in_f;
+ double d, in_d;
+ const char *str, *in_str;
+ char *out;
+ char buf[256];
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_CHAR);
+ fail_unless(value != NULL);
+ in_c = 'x';
+ fail_unless(eina_value_pset(value, &in_c));
+ fail_unless(eina_value_pget(value, &c));
+ fail_unless(c == 'x');
+ snprintf(buf, sizeof(buf), "%hhd", in_c);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_SHORT));
+ in_s = 300;
+ fail_unless(eina_value_pset(value, &in_s));
+ fail_unless(eina_value_pget(value, &s));
+ fail_unless(s == 300);
+ snprintf(buf, sizeof(buf), "%hd", in_s);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT));
+ in_i = -12345;
+ fail_unless(eina_value_pset(value, &in_i));
+ fail_unless(eina_value_pget(value, &i));
+ fail_unless(i == -12345);
+ snprintf(buf, sizeof(buf), "%d", in_i);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_LONG));
+ in_l = 0xb33f;
+ fail_unless(eina_value_pset(value, &in_l));
+ fail_unless(eina_value_pget(value, &l));
+ fail_unless(l == 0xb33f);
+ snprintf(buf, sizeof(buf), "%ld", in_l);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT64));
+ in_i64 = 0x0011223344556677;
+ fail_unless(eina_value_pset(value, &in_i64));
+ fail_unless(eina_value_pget(value, &i64));
+ fail_unless(i64 == 0x0011223344556677);
+ snprintf(buf, sizeof(buf), "%"PRId64, in_i64);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ /* unsigned: */
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UCHAR));
+ in_uc = 200;
+ fail_unless(eina_value_pset(value, &in_uc));
+ fail_unless(eina_value_pget(value, &uc));
+ fail_unless(uc == 200);
+ snprintf(buf, sizeof(buf), "%hhu", in_uc);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_USHORT));
+ in_us = 65535;
+ fail_unless(eina_value_pset(value, &in_us));
+ fail_unless(eina_value_pget(value, &us));
+ fail_unless(us == 65535);
+ snprintf(buf, sizeof(buf), "%hu", in_us);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT));
+ in_ui = 4000000000U;
+ fail_unless(eina_value_pset(value, &in_ui));
+ fail_unless(eina_value_pget(value, &ui));
+ fail_unless(ui == 4000000000U);
+ snprintf(buf, sizeof(buf), "%u", in_ui);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_ULONG));
+ in_ul = 3000000001UL;
+ fail_unless(eina_value_pset(value, &in_ul));
+ fail_unless(eina_value_pget(value, &ul));
+ fail_unless(ul == 3000000001UL);
+ snprintf(buf, sizeof(buf), "%lu", in_ul);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT64));
+ in_u64 = 0x1122334455667788;
+ fail_unless(eina_value_pset(value, &in_u64));
+ fail_unless(eina_value_pget(value, &u64));
+ fail_unless(u64 == 0x1122334455667788);
+ snprintf(buf, sizeof(buf), "%"PRIu64, in_u64);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(buf, out) == 0);
+ free(out);
+ eina_value_flush(value);
+
+ /* floating point */
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_FLOAT));
+ in_f = 0.1234;
+ fail_unless(eina_value_pset(value, &in_f));
+ fail_unless(eina_value_pget(value, &f));
+ fail_unless(CHECK_FP(0.1234, f));
+ snprintf(buf, sizeof(buf), "%g", in_f);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strncmp(buf, out, 6) == 0); /* stupid float... */
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_DOUBLE));
+ in_d = 34567.8;
+ fail_unless(eina_value_pset(value, &in_d));
+ fail_unless(eina_value_pget(value, &d));
+ fail_unless(CHECK_FP(34567.8, d));
+ snprintf(buf, sizeof(buf), "%g", in_d);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strncmp(buf, out, 7) == 0); /* stupid double... */
+ free(out);
+ eina_value_flush(value);
+
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING));
+ in_str = "hello world!";
+ fail_unless(eina_value_pset(value, &in_str));
+ fail_unless(eina_value_pget(value, &str));
+ fail_unless(strcmp(str, "hello world!") == 0);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(in_str, out) == 0);
+ free(out);
+
+ in_str = "eina-value";
+ fail_unless(eina_value_pset(value, &in_str));
+ fail_unless(eina_value_pget(value, &str));
+ fail_unless(strcmp(str, "eina-value") == 0);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(in_str, out) == 0);
+ free(out);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING));
+
+ in_str = "profusion";
+ fail_unless(eina_value_pset(value, &in_str));
+ fail_unless(eina_value_pget(value, &str));
+ fail_unless(strcmp(str, "profusion") == 0);
+ out = eina_value_to_string(value);
+ fail_unless(out != NULL);
+ fail_unless(strcmp(in_str, out) == 0);
+ free(out);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_convert_char)
+{
+ Eina_Value *value, conv;
+ char c;
+ short s;
+ int i;
+ long l;
+ int64_t i64;
+ unsigned char uc;
+ unsigned short us;
+ unsigned int ui;
+ unsigned long ul;
+ uint64_t u64;
+ float f;
+ double d;
+ const char *str;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_CHAR);
+ fail_unless(value != NULL);
+
+ fail_unless(eina_value_set(value, 123));
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UCHAR));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &uc));
+ fail_unless(uc == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_USHORT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &us));
+ fail_unless(us == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &ui));
+ fail_unless(ui == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_ULONG));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &ul));
+ fail_unless(ul == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT64));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &u64));
+ fail_unless(u64 == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_CHAR));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &c));
+ fail_unless(c == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_SHORT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &s));
+ fail_unless(s == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &i));
+ fail_unless(i == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_LONG));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &l));
+ fail_unless(l == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT64));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &i64));
+ fail_unless(i64 == 123);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_FLOAT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &f));
+ fail_unless(CHECK_FP(f, 123));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_DOUBLE));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &d));
+ fail_unless(CHECK_FP(d, 123));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_STRING));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &str));
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "123") == 0);
+ eina_value_flush(&conv);
+
+ /* negative tests */
+ fail_unless(eina_value_set(value, -123));
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UCHAR));
+ fail_if(eina_value_convert(value, &conv));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_USHORT));
+ fail_if(eina_value_convert(value, &conv));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT));
+ fail_if(eina_value_convert(value, &conv));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_ULONG));
+ fail_if(eina_value_convert(value, &conv));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT64));
+ fail_if(eina_value_convert(value, &conv));
+ eina_value_flush(&conv);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_convert_uchar)
+{
+ Eina_Value *value, conv;
+ char c;
+ short s;
+ int i;
+ long l;
+ int64_t i64;
+ unsigned char uc;
+ unsigned short us;
+ unsigned int ui;
+ unsigned long ul;
+ uint64_t u64;
+ float f;
+ double d;
+ const char *str;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_UCHAR);
+ fail_unless(value != NULL);
+
+ fail_unless(eina_value_set(value, 31));
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UCHAR));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &uc));
+ fail_unless(uc == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_USHORT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &us));
+ fail_unless(us == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &ui));
+ fail_unless(ui == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_ULONG));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &ul));
+ fail_unless(ul == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT64));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &u64));
+ fail_unless(u64 == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_CHAR));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &c));
+ fail_unless(c == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_SHORT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &s));
+ fail_unless(s == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &i));
+ fail_unless(i == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_LONG));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &l));
+ fail_unless(l == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT64));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &i64));
+ fail_unless(i64 == 31);
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_FLOAT));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &f));
+ fail_unless(CHECK_FP(f, 31));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_DOUBLE));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &d));
+ fail_unless(CHECK_FP(d, 31));
+ eina_value_flush(&conv);
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_STRING));
+ fail_unless(eina_value_convert(value, &conv));
+ fail_unless(eina_value_get(&conv, &str));
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "31") == 0);
+ eina_value_flush(&conv);
+
+ /* negative tests */
+ fail_unless(eina_value_set(value, 200));
+
+ fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_CHAR));
+ fail_if(eina_value_convert(value, &conv));
+ eina_value_flush(&conv);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_value_test_array)
+{
+ Eina_Value *value, other;
+ Eina_Value_Array desc;
+ Eina_Inarray *inarray;
+ char c;
+ char buf[1024];
+ char *str;
+
+ eina_init();
+
+ value = eina_value_array_new(EINA_VALUE_TYPE_CHAR, 0);
+ fail_unless(value != NULL);
+
+ fail_unless(eina_value_array_append(value, 'k'));
+ fail_unless(eina_value_array_append(value, '-'));
+ fail_unless(eina_value_array_append(value, 's'));
+
+ fail_unless(eina_value_array_get(value, 0, &c));
+ fail_unless(c == 'k');
+ fail_unless(eina_value_array_get(value, 1, &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_array_get(value, 2, &c));
+ fail_unless(c == 's');
+
+ fail_unless(eina_value_array_insert(value, 0, '!'));
+ fail_unless(eina_value_array_get(value, 0, &c));
+ fail_unless(c == '!');
+ fail_unless(eina_value_array_get(value, 1, &c));
+ fail_unless(c == 'k');
+ fail_unless(eina_value_array_get(value, 2, &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_array_get(value, 3, &c));
+ fail_unless(c == 's');
+
+ fail_unless(eina_value_array_set(value, 0, '*'));
+ fail_unless(eina_value_array_get(value, 0, &c));
+ fail_unless(c == '*');
+ fail_unless(eina_value_array_get(value, 1, &c));
+ fail_unless(c == 'k');
+ fail_unless(eina_value_array_get(value, 2, &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_array_get(value, 3, &c));
+ fail_unless(c == 's');
+
+ snprintf(buf, sizeof(buf), "[%hhd, %hhd, %hhd, %hhd]",
+ '*', 'k', '-', 's');
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, buf) == 0);
+ free(str);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_array_setup(value, EINA_VALUE_TYPE_STRINGSHARE, 2));
+
+ fail_unless(eina_value_array_append(value, "Enlightenment.org"));
+ fail_unless(eina_value_array_append(value, "X11"));
+ fail_unless(eina_value_array_append(value, "Pants"));
+ fail_unless(eina_value_array_append(value, "on!!!"));
+ fail_unless(eina_value_array_append(value, "k-s"));
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "[Enlightenment.org, X11, Pants, on!!!, k-s]") == 0);
+ free(str);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_array_setup(value, EINA_VALUE_TYPE_CHAR, 0));
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_CHAR));
+
+ fail_unless(eina_value_set(&other, 100));
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c == 100);
+
+ fail_unless(eina_value_convert(&other, value));
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "[100]") == 0);
+ free(str);
+
+ fail_unless(eina_value_array_set(value, 0, 33));
+ fail_unless(eina_value_convert(value, &other));
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c == 33);
+
+ inarray = eina_inarray_new(sizeof(char), 0);
+ fail_unless(inarray != NULL);
+ c = 11;
+ fail_unless(eina_inarray_push(inarray, &c) >= 0);
+ c = 21;
+ fail_unless(eina_inarray_push(inarray, &c) >= 0);
+ c = 31;
+ fail_unless(eina_inarray_push(inarray, &c) >= 0);
+ desc.subtype = EINA_VALUE_TYPE_CHAR;
+ desc.step = 0;
+ desc.array = inarray;
+ fail_unless(eina_value_set(value, desc)); /* manually configure */
+ eina_inarray_free(inarray);
+
+ fail_unless(eina_value_array_get(value, 0, &c));
+ fail_unless(c == 11);
+ fail_unless(eina_value_array_get(value, 1, &c));
+ fail_unless(c == 21);
+ fail_unless(eina_value_array_get(value, 2, &c));
+ fail_unless(c == 31);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_list)
+{
+ Eina_Value *value, other;
+ Eina_Value_List desc;
+ char c;
+ char buf[1024];
+ char *str;
+ const char *s;
+
+ eina_init();
+
+ value = eina_value_list_new(EINA_VALUE_TYPE_CHAR);
+ fail_unless(value != NULL);
+
+ fail_unless(eina_value_list_append(value, 'k'));
+ fail_unless(eina_value_list_append(value, '-'));
+ fail_unless(eina_value_list_append(value, 's'));
+
+ fail_unless(eina_value_list_get(value, 0, &c));
+ fail_unless(c == 'k');
+ fail_unless(eina_value_list_get(value, 1, &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_list_get(value, 2, &c));
+ fail_unless(c == 's');
+
+ fail_unless(eina_value_list_insert(value, 0, '!'));
+ fail_unless(eina_value_list_get(value, 0, &c));
+ fail_unless(c == '!');
+ fail_unless(eina_value_list_get(value, 1, &c));
+ fail_unless(c == 'k');
+ fail_unless(eina_value_list_get(value, 2, &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_list_get(value, 3, &c));
+ fail_unless(c == 's');
+
+ fail_unless(eina_value_list_set(value, 0, '*'));
+ fail_unless(eina_value_list_get(value, 0, &c));
+ fail_unless(c == '*');
+ fail_unless(eina_value_list_get(value, 1, &c));
+ fail_unless(c == 'k');
+ fail_unless(eina_value_list_get(value, 2, &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_list_get(value, 3, &c));
+ fail_unless(c == 's');
+
+ snprintf(buf, sizeof(buf), "[%hhd, %hhd, %hhd, %hhd]",
+ '*', 'k', '-', 's');
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, buf) == 0);
+ free(str);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_list_setup(value, EINA_VALUE_TYPE_STRINGSHARE));
+
+ fail_unless(eina_value_list_append(value, "Enlightenment.org"));
+ fail_unless(eina_value_list_append(value, "X11"));
+ fail_unless(eina_value_list_append(value, "Pants"));
+ fail_unless(eina_value_list_append(value, "on!!!"));
+ fail_unless(eina_value_list_append(value, "k-s"));
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "[Enlightenment.org, X11, Pants, on!!!, k-s]") == 0);
+ free(str);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_list_setup(value, EINA_VALUE_TYPE_CHAR));
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_CHAR));
+
+ fail_unless(eina_value_set(&other, 100));
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c == 100);
+
+ fail_unless(eina_value_convert(&other, value));
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "[100]") == 0);
+ free(str);
+
+ fail_unless(eina_value_list_set(value, 0, 33));
+ fail_unless(eina_value_convert(value, &other));
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c == 33);
+
+ desc.subtype = EINA_VALUE_TYPE_STRING;
+ desc.list = NULL;
+ desc.list = eina_list_append(desc.list, "hello");
+ desc.list = eina_list_append(desc.list, "world");
+ desc.list = eina_list_append(desc.list, "eina");
+ fail_unless(eina_list_count(desc.list) == 3);
+ fail_unless(eina_value_set(value, desc));
+ eina_list_free(desc.list);
+
+ fail_unless(eina_value_list_get(value, 0, &s));
+ fail_unless(s != NULL);
+ fail_unless(strcmp(s, "hello") == 0);
+ fail_unless(eina_value_list_get(value, 1, &s));
+ fail_unless(s != NULL);
+ fail_unless(strcmp(s, "world") == 0);
+ fail_unless(eina_value_list_get(value, 2, &s));
+ fail_unless(s != NULL);
+ fail_unless(strcmp(s, "eina") == 0);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_value_test_hash)
+{
+ Eina_Value *value, other;
+ Eina_Value_Hash desc;
+ char c;
+ char buf[1024];
+ char **ptr;
+ char *str;
+ const char *s;
+
+ eina_init();
+
+ value = eina_value_hash_new(EINA_VALUE_TYPE_CHAR, 0);
+ fail_unless(value != NULL);
+
+ fail_unless(eina_value_hash_set(value, "first", 'k'));
+ fail_unless(eina_value_hash_set(value, "second", '-'));
+ fail_unless(eina_value_hash_set(value, "third", 's'));
+
+ fail_unless(eina_value_hash_get(value, "first", &c));
+ fail_unless(c == 'k');
+ fail_unless(eina_value_hash_get(value, "second", &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_hash_get(value, "third", &c));
+ fail_unless(c == 's');
+
+ fail_unless(eina_value_hash_set(value, "first", '!'));
+ fail_unless(eina_value_hash_get(value, "first", &c));
+ fail_unless(c == '!');
+ fail_unless(eina_value_hash_get(value, "second", &c));
+ fail_unless(c == '-');
+ fail_unless(eina_value_hash_get(value, "third", &c));
+ fail_unless(c == 's');
+
+ puts("testing hash to string -- may fail due hash algorithm changes!");
+
+ /* watchout, this is the order I got -- hash algorithm changes may change
+ * the order!
+ */
+ snprintf(buf, sizeof(buf), "{first: %hhd, second: %hhd, third: %hhd}",
+ '!', '-', 's');
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ printf("want: %s\n", buf);
+ printf("got.: %s\n", str);
+ fail_unless(strcmp(str, buf) == 0);
+ free(str);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_hash_setup(value, EINA_VALUE_TYPE_STRINGSHARE, 0));
+
+ fail_unless(eina_value_hash_set(value, "a", "Enlightenment.org"));
+ fail_unless(eina_value_hash_set(value, "b", "X11"));
+ fail_unless(eina_value_hash_set(value, "c", "Pants"));
+ fail_unless(eina_value_hash_set(value, "d", "on!!!"));
+ fail_unless(eina_value_hash_set(value, "e", "k-s"));
+
+ /* watchout, this is the order I got -- hash algorithm changes may change
+ * the order!
+ */
+ strcpy(buf, "{e: k-s, d: on!!!, a: Enlightenment.org, b: X11, c: Pants}");
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ printf("want: %s\n", buf);
+ printf("got.: %s\n", str);
+ fail_unless(strcmp(str, buf) == 0);
+ free(str);
+
+ eina_value_flush(value);
+ fail_unless(eina_value_hash_setup(value, EINA_VALUE_TYPE_CHAR, 0));
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_CHAR));
+
+ fail_unless(eina_value_set(&other, 100));
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c == 100);
+
+ fail_unless(eina_value_hash_set(value, "first", 33));
+ fail_unless(eina_value_convert(value, &other));
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c == 33);
+
+ desc.subtype = EINA_VALUE_TYPE_STRING;
+ desc.buckets_power_size = 0;
+ desc.hash = eina_hash_string_small_new(NULL);
+ fail_unless(desc.hash != NULL);
+ /* watch out hash pointer is to a size of subtype->value_size! */
+ ptr = malloc(sizeof(char *));
+ *ptr = "there";
+ fail_unless(eina_hash_add(desc.hash, "hi", ptr));
+ ptr = malloc(sizeof(char *));
+ *ptr = "y";
+ fail_unless(eina_hash_add(desc.hash, "x", ptr));
+ fail_unless(eina_value_set(value, desc));
+
+ free(eina_hash_find(desc.hash, "hi"));
+ free(eina_hash_find(desc.hash, "x"));
+ eina_hash_free(desc.hash);
+
+ fail_unless(eina_value_hash_get(value, "hi", &s));
+ fail_unless(s != NULL);
+ fail_unless(strcmp(s, "there") == 0);
+
+ fail_unless(eina_value_hash_get(value, "x", &s));
+ fail_unless(s != NULL);
+ fail_unless(strcmp(s, "y") == 0);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_value_test_timeval)
+{
+ Eina_Value *value, other;
+ struct timeval itv, otv;
+ char c;
+ char *str;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_TIMEVAL);
+ fail_unless(value != NULL);
+
+ itv.tv_sec = 1;
+ itv.tv_usec = 123;
+ fail_unless(eina_value_set(value, itv));
+ fail_unless(eina_value_get(value, &otv));
+ fail_unless(memcmp(&itv, &otv, sizeof(struct timeval)) == 0);
+
+ itv.tv_sec = 3;
+ itv.tv_usec = -1;
+ fail_unless(eina_value_set(value, itv));
+ fail_unless(eina_value_get(value, &otv));
+ itv.tv_sec = 2;
+ itv.tv_usec = 999999;
+ fail_unless(memcmp(&itv, &otv, sizeof(struct timeval)) == 0);
+
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_CHAR));
+ fail_unless(eina_value_convert(value, &other));
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c == 2);
+ eina_value_flush(&other);
+
+ itv.tv_sec = 12345;
+ itv.tv_usec = 6789;
+ fail_unless(eina_value_set(value, itv));
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "12345.006789") == 0);
+ free(str);
+
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_TIMEVAL));
+ fail_unless(eina_value_set(&other, itv));
+ fail_unless(eina_value_compare(value, &other) == 0);
+
+ itv.tv_sec++;
+ fail_unless(eina_value_set(&other, itv));
+ fail_unless(eina_value_compare(value, &other) < 0);
+
+ itv.tv_sec -= 2;
+ fail_unless(eina_value_set(&other, itv));
+ fail_unless(eina_value_compare(value, &other) > 0);
+
+ itv.tv_sec++;
+ fail_unless(eina_value_set(&other, itv));
+ fail_unless(eina_value_compare(value, &other) == 0);
+
+ itv.tv_usec++;
+ fail_unless(eina_value_set(&other, itv));
+ fail_unless(eina_value_compare(value, &other) < 0);
+
+ itv.tv_usec -= 2;
+ fail_unless(eina_value_set(&other, itv));
+ fail_unless(eina_value_compare(value, &other) > 0);
+
+ itv.tv_usec++;
+ fail_unless(eina_value_set(&other, itv));
+ fail_unless(eina_value_compare(value, &other) == 0);
+
+ eina_value_flush(&other);
+
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_value_test_blob)
+{
+ Eina_Value *value, other;
+ Eina_Value_Blob in, out;
+ unsigned char blob[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ int i = 0x11223344;
+ char *str;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_BLOB);
+ fail_unless(value != NULL);
+
+ in.ops = NULL;
+ in.memory = blob;
+ in.size = sizeof(blob);
+ fail_unless(eina_value_set(value, in));
+ fail_unless(eina_value_get(value, &out));
+ fail_unless(out.memory == blob);
+ fail_unless(out.size == sizeof(blob));
+ fail_unless(memcmp(&in, &out, sizeof(Eina_Value_Blob)) == 0);
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "BLOB(10, [01 02 03 04 05 06 07 08 09 0a])") == 0);
+ free(str);
+
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&other, i));
+ fail_unless(eina_value_convert(&other, value));
+ fail_unless(eina_value_get(value, &out));
+
+ fail_unless(out.memory != NULL);
+ fail_unless(out.size == sizeof(int));
+ fail_unless(memcmp(&i, out.memory, sizeof(int)) == 0);
+
+ eina_value_flush(&other);
+
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_STRING));
+ fail_unless(eina_value_set(&other, "hi there!"));
+ fail_unless(eina_value_convert(&other, value));
+ fail_unless(eina_value_get(value, &out));
+ fail_unless(out.memory != NULL);
+ fail_unless(out.size == sizeof("hi there!"));
+ fail_unless(strcmp(out.memory, "hi there!") == 0);
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "BLOB(10, [68 69 20 74 68 65 72 65 21 00])") == 0);
+ free(str);
+
+ eina_value_flush(&other);
+
+ fail_unless(eina_value_array_setup(&other, EINA_VALUE_TYPE_CHAR, 0));
+ fail_unless(eina_value_array_append(&other, 0xa));
+ fail_unless(eina_value_array_append(&other, 0xb));
+ fail_unless(eina_value_array_append(&other, 0xc));
+ fail_unless(eina_value_convert(&other, value));
+ fail_unless(eina_value_get(value, &out));
+ fail_unless(out.memory != NULL);
+ fail_unless(out.size == 3);
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "BLOB(3, [0a 0b 0c])") == 0);
+ free(str);
+
+ eina_value_flush(&other);
+
+ fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_BLOB));
+ fail_unless(eina_value_set(&other, in));
+ fail_unless(eina_value_convert(value, &other));
+ fail_unless(eina_value_get(&other, &out));
+ fail_unless(out.memory != NULL);
+ fail_unless(out.size == 3);
+
+ str = eina_value_to_string(&other);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "BLOB(3, [0a 0b 0c])") == 0);
+ free(str);
+
+ eina_value_flush(&other);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_value_test_struct)
+{
+ struct mybigst {
+ int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, x;
+ };
+ const Eina_Value_Struct_Member mybigst_members[] = {
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, a),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, b),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, c),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, d),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, e),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, f),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, g),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, h),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, i),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, j),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, k),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, l),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, m),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, n),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, o),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, p),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, q),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, r),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, s),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, t),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, u),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, v),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, x),
+ EINA_VALUE_STRUCT_MEMBER_SENTINEL
+ };
+ const Eina_Value_Struct_Desc mybigst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH,
+ mybigst_members, 23, sizeof(struct mybigst)
+ };
+ struct myst {
+ int i;
+ char c;
+ };
+ const Eina_Value_Struct_Member myst_members[] = {
+ {"i", EINA_VALUE_TYPE_INT, 0},
+ {"c", EINA_VALUE_TYPE_CHAR, 4},
+ {NULL, NULL, 0}
+ };
+ const Eina_Value_Struct_Desc myst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ NULL, myst_members, 2, sizeof(struct myst)
+ };
+ Eina_Value *value, other;
+ int i;
+ char c;
+ char *str;
+
+ eina_init();
+
+ value = eina_value_struct_new(&myst_desc);
+ fail_unless(value != NULL);
+
+ fail_unless(eina_value_struct_set(value, "i", 5678));
+ fail_unless(eina_value_struct_set(value, "c", 0xf));
+
+ fail_unless(eina_value_struct_get(value, "i", &i));
+ fail_unless(i == 5678);
+ fail_unless(eina_value_struct_get(value, "c", &c));
+ fail_unless(c == 0xf);
+
+ fail_unless(eina_value_struct_member_value_get
+ (value, myst_members + 0, &other));
+ fail_unless(other.type == EINA_VALUE_TYPE_INT);
+ fail_unless(eina_value_get(&other, &i));
+ fail_unless(i == 5678);
+ eina_value_flush(&other);
+
+ fail_unless(eina_value_struct_member_value_get
+ (value, myst_members + 1, &other));
+ fail_unless(other.type == EINA_VALUE_TYPE_CHAR);
+ fail_unless(eina_value_get(&other, &c));
+ fail_unless(c = 0xf);
+ eina_value_flush(&other);
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "{i: 5678, c: 15}") == 0);
+ free(str);
+
+ fail_if(eina_value_struct_get(value, "x", 1234));
+
+ i = 0x11223344;
+ fail_unless(eina_value_struct_pset(value, "i", &i));
+ i = -1;
+ fail_unless(eina_value_struct_pget(value, "i", &i));
+ fail_unless(i == 0x11223344);
+
+ fail_unless(eina_value_copy(value, &other));
+ str = eina_value_to_string(&other);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "{i: 287454020, c: 15}") == 0);
+ free(str);
+
+ eina_value_flush(&other);
+
+ fail_unless(eina_value_struct_setup(&other, &mybigst_desc));
+ fail_unless(eina_value_struct_set(&other, "a", 1) );
+ fail_unless(eina_value_struct_set(&other, "b", 2));
+ fail_unless(eina_value_struct_set(&other, "c", 3));
+ fail_unless(eina_value_struct_set(&other, "d", 4));
+ fail_unless(eina_value_struct_set(&other, "e", 5));
+ fail_unless(eina_value_struct_set(&other, "f", 6));
+ fail_unless(eina_value_struct_set(&other, "g", 7));
+ fail_unless(eina_value_struct_set(&other, "h", 8));
+ fail_unless(eina_value_struct_set(&other, "i", 9));
+ fail_unless(eina_value_struct_set(&other, "j", 10));
+ fail_unless(eina_value_struct_set(&other, "k", 12));
+ fail_unless(eina_value_struct_set(&other, "l", 13));
+ fail_unless(eina_value_struct_set(&other, "m", 14));
+ fail_unless(eina_value_struct_set(&other, "n", 15));
+ fail_unless(eina_value_struct_set(&other, "o", 16));
+ fail_unless(eina_value_struct_set(&other, "p", 17));
+ fail_unless(eina_value_struct_set(&other, "q", 18));
+ fail_unless(eina_value_struct_set(&other, "r", 19));
+ fail_unless(eina_value_struct_set(&other, "s", 20));
+ fail_unless(eina_value_struct_set(&other, "t", 21));
+ fail_unless(eina_value_struct_set(&other, "u", 22));
+ fail_unless(eina_value_struct_set(&other, "v", 23));
+ fail_unless(eina_value_struct_set(&other, "x", 24));
+
+ fail_unless(eina_value_struct_get(&other, "a", &i));
+ fail_unless(i == 1);
+ fail_unless(eina_value_struct_get(&other, "b", &i));
+ fail_unless(i == 2);
+ fail_unless(eina_value_struct_get(&other, "c", &i));
+ fail_unless(i == 3);
+ fail_unless(eina_value_struct_get(&other, "d", &i));
+ fail_unless(i == 4);
+ fail_unless(eina_value_struct_get(&other, "e", &i));
+ fail_unless(i == 5);
+ fail_unless(eina_value_struct_get(&other, "f", &i));
+ fail_unless(i == 6);
+ fail_unless(eina_value_struct_get(&other, "g", &i));
+ fail_unless(i == 7);
+ fail_unless(eina_value_struct_get(&other, "h", &i));
+ fail_unless(i == 8);
+ fail_unless(eina_value_struct_get(&other, "i", &i));
+ fail_unless(i == 9);
+ fail_unless(eina_value_struct_get(&other, "j", &i));
+ fail_unless(i == 10);
+ fail_unless(eina_value_struct_get(&other, "k", &i));
+ fail_unless(i == 12);
+ fail_unless(eina_value_struct_get(&other, "l", &i));
+ fail_unless(i == 13);
+ fail_unless(eina_value_struct_get(&other, "m", &i));
+ fail_unless(i == 14);
+ fail_unless(eina_value_struct_get(&other, "n", &i));
+ fail_unless(i == 15);
+ fail_unless(eina_value_struct_get(&other, "o", &i));
+ fail_unless(i == 16);
+ fail_unless(eina_value_struct_get(&other, "p", &i));
+ fail_unless(i == 17);
+ fail_unless(eina_value_struct_get(&other, "q", &i));
+ fail_unless(i == 18);
+ fail_unless(eina_value_struct_get(&other, "r", &i));
+ fail_unless(i == 19);
+ fail_unless(eina_value_struct_get(&other, "s", &i));
+ fail_unless(i == 20);
+ fail_unless(eina_value_struct_get(&other, "t", &i));
+ fail_unless(i == 21);
+ fail_unless(eina_value_struct_get(&other, "u", &i));
+ fail_unless(i == 22);
+ fail_unless(eina_value_struct_get(&other, "v", &i));
+ fail_unless(i == 23);
+ fail_unless(eina_value_struct_get(&other, "x", &i));
+ fail_unless(i == 24);
+
+ str = eina_value_to_string(&other);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10, k: 12, l: 13, m: 14, n: 15, o: 16, p: 17, q: 18, r: 19, s: 20, t: 21, u: 22, v: 23, x: 24}") == 0);
+ free(str);
+
+ eina_value_flush(&other);
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+
+START_TEST(eina_value_test_array_of_struct)
+{
+ struct myst {
+ int a, b, c;
+ const char *s;
+ };
+ const Eina_Value_Struct_Member myst_members[] = {
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct myst, a),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct myst, b),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct myst, c),
+ EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_STRING, struct myst, s),
+ EINA_VALUE_STRUCT_MEMBER_SENTINEL
+ };
+ const Eina_Value_Struct_Desc myst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH,
+ myst_members, 4, sizeof(struct myst)
+ };
+ Eina_Value *value, array_item;
+ char *str;
+ int i;
+
+ eina_init();
+
+ value = eina_value_array_new(EINA_VALUE_TYPE_STRUCT, 0);
+ fail_unless(value != NULL);
+
+ for (i = 0; i < 10; i++)
+ {
+ Eina_Value_Struct desc;
+ struct myst st;
+ char buf[64];
+
+ snprintf(buf, sizeof(buf), "item%02d", i);
+ st.a = i;
+ st.b = i * 10;
+ st.c = i * 100;
+ st.s = buf;
+
+ desc.desc = &myst_desc;
+ desc.memory = &st;
+ fail_unless(eina_value_array_append(value, desc));
+ }
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "["
+ "{a: 0, b: 0, c: 0, s: item00}, "
+ "{a: 1, b: 10, c: 100, s: item01}, "
+ "{a: 2, b: 20, c: 200, s: item02}, "
+ "{a: 3, b: 30, c: 300, s: item03}, "
+ "{a: 4, b: 40, c: 400, s: item04}, "
+ "{a: 5, b: 50, c: 500, s: item05}, "
+ "{a: 6, b: 60, c: 600, s: item06}, "
+ "{a: 7, b: 70, c: 700, s: item07}, "
+ "{a: 8, b: 80, c: 800, s: item08}, "
+ "{a: 9, b: 90, c: 900, s: item09}"
+ "]") == 0);
+ free(str);
+
+ eina_value_array_value_get(value, 2, &array_item);
+ eina_value_struct_get(&array_item, "a", &i);
+ ck_assert_int_eq(i, 2);
+ eina_value_struct_get(&array_item, "b", &i);
+ ck_assert_int_eq(i, 20);
+ eina_value_struct_get(&array_item, "c", &i);
+ ck_assert_int_eq(i, 200);
+ eina_value_struct_get(&array_item, "s", &str);
+ ck_assert_str_eq(str, "item02");
+ eina_value_flush(&array_item);
+
+ eina_value_free(value);
+ eina_shutdown();
+}
+END_TEST
+
+#if 0
+START_TEST(eina_value_test_model)
+{
+ Eina_Value *value, inv;
+ Eina_Model *model, *m;
+ char *str;
+
+ eina_init();
+
+ value = eina_value_new(EINA_VALUE_TYPE_MODEL);
+ fail_unless(value != NULL);
+
+ model = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+ fail_unless(model != NULL);
+
+ fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_INT));
+ fail_unless(eina_value_set(&inv, 1234));
+ fail_unless(eina_model_property_set(model, "i", &inv));
+ eina_value_flush(&inv);
+
+ fail_unless(eina_value_set(value, model));
+ fail_unless(eina_model_refcount(model) == 2);
+
+ fail_unless(eina_value_get(value, &m));
+ fail_unless(m == model);
+ fail_unless(eina_model_refcount(m) == 2);
+
+ fail_unless(eina_value_pset(value, &model));
+ fail_unless(eina_model_refcount(model) == 2);
+
+ str = eina_value_to_string(value);
+ fail_unless(str != NULL);
+ fail_unless(strcmp(str, "Eina_Model_Type_Generic({i: 1234}, [])") == 0);
+ free(str);
+
+ eina_value_free(value);
+
+ fail_unless(eina_model_refcount(model) == 1);
+ eina_model_unref(model);
+
+ eina_shutdown();
+}
+END_TEST
+#endif
+
+void
+eina_test_value(TCase *tc)
+{
+ tcase_add_test(tc, eina_value_test_simple);
+ tcase_add_test(tc, eina_value_test_string);
+ tcase_add_test(tc, eina_value_test_pvariant);
+ tcase_add_test(tc, eina_value_test_compare);
+ tcase_add_test(tc, eina_value_test_to_string);
+ tcase_add_test(tc, eina_value_test_convert_char);
+ tcase_add_test(tc, eina_value_test_convert_uchar);
+ // TODO: other converters...
+ tcase_add_test(tc, eina_value_test_array);
+ tcase_add_test(tc, eina_value_test_list);
+ tcase_add_test(tc, eina_value_test_hash);
+ tcase_add_test(tc, eina_value_test_timeval);
+ tcase_add_test(tc, eina_value_test_blob);
+ tcase_add_test(tc, eina_value_test_struct);
+ tcase_add_test(tc, eina_value_test_array_of_struct);
+#if 0
+ tcase_add_test(tc, eina_value_test_model);
+#endif
+}
diff --git a/src/tests/eina/evas_hash.c b/src/tests/eina/evas_hash.c
new file mode 100644
index 000000000..33615afa7
--- /dev/null
+++ b/src/tests/eina/evas_hash.c
@@ -0,0 +1,536 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "Evas_Data.h"
+
+typedef struct _Evas_Hash_El Evas_Hash_El;
+
+struct _Evas_Hash_El
+{
+ Evas_Object_List _list_data;
+ const char *key;
+ void *data;
+};
+
+static inline int _evas_hash_gen(const char *key);
+
+static int _evas_hash_alloc_error = 0;
+
+static inline int
+_evas_hash_gen(const char *key)
+{
+ unsigned int hash_num = 5381;
+ const unsigned char *ptr;
+
+ if (!key)
+ return 0;
+
+ for (ptr = (unsigned char *)key; *ptr; ptr++)
+ hash_num = (hash_num * 33) ^ *ptr;
+
+ hash_num &= 0xff;
+ return (int)hash_num;
+}
+
+/**
+ * @defgroup Evas_Hash_Data Hash Data Functions
+ *
+ * Functions that add, access or remove data from hashes.
+ *
+ * The following example shows how to add and then access data in a
+ * hash table:
+ * @code
+ * Evas_Hash *hash = NULL;
+ * extern void *my_data;
+ *
+ * hash = evas_hash_add(hash, "My Data", my_data);
+ * if (evas_hash_alloc_error())
+ * {
+ * fprintf(stderr, "ERROR: Memory is low. Hash allocation failed.\n");
+ * exit(-1);
+ * }
+ * if (evas_hash_find(hash, "My Data") == my_data)
+ * {
+ * printf("My Data inserted and successfully found.\n");
+ * }
+ * @endcode
+ *
+ * What follows is another example, showing how the @ref evas_hash_del
+ * function is used:
+ * @code
+ * extern Evas_Hash *hash;
+ * extern void *data;
+ *
+ * printf("Insert some data...\n");
+ * hash = evas_hash_add(hash, "My Data", my_data);
+ * printf("Removing by key...\n");
+ * hash = evas_hash_del(hash, "My Data", NULL);
+ * printf("Insert some more data as a NULL key...\n");
+ * hash = evas_hash_add(hash, NULL, my_data);
+ * printf("Removing by data as a NULL key...\n");
+ * hash = evas_hash_del(hash, NULL, my_data);
+ * @endcode
+ */
+
+/**
+ * Adds an entry to the given hash table.
+ *
+ * @p key is expected to be a unique string within the hash table.
+ * Otherwise, you cannot be sure which inserted data pointer will be
+ * accessed with @ref evas_hash_find , and removed with
+ * @ref evas_hash_del .
+ *
+ * Key strings are case sensitive.
+ *
+ * @ref evas_hash_alloc_error should be used to determine if an
+ * allocation error occurred during this function.
+ *
+ * @param hash The given hash table. Can be @c NULL, in which case a
+ * new hash table is allocated and returned.
+ * @param key A unique string. Can be @c NULL.
+ * @param data Data to associate with the string given by @p key.
+ * @return Either the given hash table, or if the given value for @p
+ * hash is @c NULL, then a new one. @c NULL will be returned
+ * if memory could not be allocated for a new table.
+ * @ingroup Evas_Hash_Data
+ */
+EAPI Evas_Hash *
+evas_hash_add(Evas_Hash *hash, const char *key, const void *data)
+{
+ int hash_num;
+ Evas_Hash_El *el;
+
+ if ((!key) || (!data))
+ return hash;
+
+ _evas_hash_alloc_error = 0;
+ if (!hash)
+ {
+ hash = calloc(1, sizeof(struct _Evas_Hash));
+ if (!hash)
+ {
+ _evas_hash_alloc_error = 1;
+ return NULL;
+ }
+ }
+
+ if (!(el = malloc(sizeof(struct _Evas_Hash_El) + strlen(key) + 1)))
+ {
+ if (hash->population <= 0)
+ {
+ free(hash);
+ hash = NULL;
+ }
+
+ _evas_hash_alloc_error = 1;
+ return hash;
+ }
+
+ el->key = ((char *)el) + sizeof(struct _Evas_Hash_El);
+ strcpy((char *)el->key, key);
+ el->data = (void *)data;
+ hash_num = _evas_hash_gen(key);
+ hash->buckets[hash_num] = evas_object_list_prepend(hash->buckets[hash_num],
+ el);
+ hash->population++;
+ return hash;
+}
+
+/**
+ * Adds an entry to the given hash table and does not duplicate the string key.
+ *
+ * @p key is expected to be a unique string within the hash table.
+ * Otherwise, you cannot be sure which inserted data pointer will be
+ * accessed with @ref evas_hash_find , and removed with
+ * @ref evas_hash_del . This call does not make a copy of the key so it must
+ * be a string constant or stored elsewhere (in the object being added) etc.
+ *
+ * Key strings are case sensitive.
+ *
+ * @ref evas_hash_alloc_error should be used to determine if an
+ * allocation error occurred during this function.
+ *
+ * @param hash The given hash table. Can be @c NULL, in which case a
+ * new hash table is allocated and returned.
+ * @param key A unique string. Can be @c NULL.
+ * @param data Data to associate with the string given by @p key.
+ * @return Either the given hash table, or if the given value for @p
+ * hash is @c NULL, then a new one. @c NULL will be returned
+ * if memory could not be allocated for a new table.
+ * @ingroup Evas_Hash_Data
+ */
+EAPI Evas_Hash *
+evas_hash_direct_add(Evas_Hash *hash, const char *key, const void *data)
+{
+ int hash_num;
+ Evas_Hash_El *el;
+
+ if ((!key) || (!data))
+ return hash;
+
+ _evas_hash_alloc_error = 0;
+ if (!hash)
+ {
+ hash = calloc(1, sizeof(struct _Evas_Hash));
+ if (!hash)
+ {
+ _evas_hash_alloc_error = 1;
+ return NULL;
+ }
+ }
+
+ if (!(el = malloc(sizeof(struct _Evas_Hash_El))))
+ {
+ if (hash->population <= 0)
+ {
+ free(hash);
+ hash = NULL;
+ }
+
+ _evas_hash_alloc_error = 1;
+ return hash;
+ }
+
+ el->key = key;
+ el->data = (void *)data;
+ hash_num = _evas_hash_gen(key);
+ hash->buckets[hash_num] = evas_object_list_prepend(hash->buckets[hash_num],
+ el);
+ hash->population++;
+ return hash;
+}
+
+/**
+ * Removes the entry identified by @p key or @p data from the given
+ * hash table.
+ *
+ * If @p key is @c NULL, then @p data is used to find a match to
+ * remove.
+ *
+ * @param hash The given hash table.
+ * @param key The key string. Can be @c NULL.
+ * @param data The data pointer to remove if @p key is @c NULL.
+ * Otherwise, not required and can be @c NULL.
+ * @return The modified hash table. If there are no entries left, the
+ * hash table will be freed and @c NULL will be returned.
+ * @ingroup Evas_Hash_Data
+ */
+EAPI Evas_Hash *
+evas_hash_del(Evas_Hash *hash, const char *key, const void *data)
+{
+ int hash_num;
+ Evas_Hash_El *el;
+ Evas_Object_List *l;
+
+ if (!hash)
+ return NULL;
+
+ if (!key)
+ for (hash_num = 0; hash_num < 256; hash_num++)
+ {
+ for (l = hash->buckets[hash_num]; l; l = l->next)
+ {
+ el = (Evas_Hash_El *)l;
+ if (el->data == data)
+ {
+ hash->buckets[hash_num] = evas_object_list_remove(
+ hash->buckets[hash_num],
+ el);
+ free(el);
+ hash->population--;
+ if (hash->population <= 0)
+ {
+ free(hash);
+ hash = NULL;
+ }
+
+ return hash;
+ }
+ }
+ }
+ else
+ {
+ hash_num = _evas_hash_gen(key);
+ for (l = hash->buckets[hash_num]; l; l = l->next)
+ {
+ el = (Evas_Hash_El *)l;
+ if (!strcmp(el->key, key))
+ if ((!data) || (el->data == data))
+ {
+ hash->buckets[hash_num] = evas_object_list_remove(