Add native Windows thread support instead of using pthread
[framework/uifw/eet.git] / src / tests / eet_suite.c
index 1176c4c..4da3b43 100644 (file)
@@ -1,3 +1,8 @@
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <pthread.h>
 
-#include <check.h>
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
+#ifdef EFL_HAVE_POSIX_THREADS
+# include <pthread.h>
 #endif
 
+#include <check.h>
+
 #include <Eina.h>
 
 #include "eet_suite.h"
@@ -364,7 +368,7 @@ _eet_build_ex_descriptor(Eet_Data_Descriptor *edd)
 static Eet_Test_Ex_Type*
 _eet_test_ex_set(Eet_Test_Ex_Type *res, int offset)
 {
-   int i;
+   unsigned int i;
 
    if (!res) res = malloc( sizeof(Eet_Test_Ex_Type));
    if (!res) return NULL;
@@ -663,7 +667,7 @@ START_TEST(eet_file_simple_write)
 
    eet_init();
 
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
 
    fail_if(eet_mode_get(NULL) != EET_FILE_MODE_INVALID);
 
@@ -671,6 +675,8 @@ START_TEST(eet_file_simple_write)
    fail_if(!ef);
 
    fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 1));
+   fail_if(!eet_alias(ef, "keys/alias", "keys/tests", 0));
+   fail_if(!eet_alias(ef, "keys/alias2", "keys/alias", 1));
 
    fail_if(eet_mode_get(ef) != EET_FILE_MODE_WRITE);
 
@@ -689,8 +695,14 @@ START_TEST(eet_file_simple_write)
 
    fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0);
 
+   test = eet_read(ef, "keys/alias2", &size);
+   fail_if(!test);
+   fail_if(size != (int) strlen(buffer) + 1);
+
+   fail_if(eet_read_direct(ef, "key/alias2", &size));
+
    fail_if(eet_mode_get(ef) != EET_FILE_MODE_READ);
-   fail_if(eet_num_entries(ef) != 1);
+   fail_if(eet_num_entries(ef) != 3);
 
    eet_close(ef);
 
@@ -755,7 +767,7 @@ START_TEST(eet_file_data_test)
 
    _eet_build_ex_descriptor(edd);
 
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
 
    /* Insert an error in etbt. */
    etbt.i = 0;
@@ -891,7 +903,7 @@ START_TEST(eet_file_data_dump_test)
 
    _eet_build_ex_descriptor(edd);
 
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
 
    /* Save the encoded data in a file. */
    ef = eet_open(file, EET_FILE_MODE_WRITE);
@@ -957,7 +969,7 @@ START_TEST(eet_image)
    unsigned int w;
    unsigned int h;
 
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
 
    /* Save the encoded data in a file. */
    ef = eet_open(file, EET_FILE_MODE_READ_WRITE);
@@ -1147,6 +1159,8 @@ START_TEST(eet_image)
 
    eet_close(ef);
 
+   fail_if(unlink(file) != 0);
+
    eet_shutdown();
 }
 END_TEST
@@ -1177,7 +1191,7 @@ START_TEST(eet_small_image)
 
    eet_init();
 
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
 
    ef = eet_open(file, EET_FILE_MODE_WRITE);
    fail_if(!ef);
@@ -1195,6 +1209,8 @@ START_TEST(eet_small_image)
 
    eet_close(ef);
 
+   fail_if(unlink(file) != 0);
+
    fail_if(data[0] != IM0);
    fail_if(data[1] != IM1);
    fail_if(data[2] != IM2);
@@ -1212,6 +1228,7 @@ START_TEST(eet_identity_simple)
    const void *tmp;
    Eet_File *ef;
    Eet_Key *k;
+   FILE *noread;
    char *test;
    char *file = strdup("/tmp/eet_suite_testXXXXXX");
    int size;
@@ -1219,8 +1236,9 @@ START_TEST(eet_identity_simple)
 
    eet_init();
 
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
    fail_if(chdir("src/tests"));
+   fail_if(!(noread = fopen("/dev/null", "w")));
 
    /* Sign an eet file. */
    ef = eet_open(file, EET_FILE_MODE_WRITE);
@@ -1232,6 +1250,7 @@ START_TEST(eet_identity_simple)
    fail_if(!k);
 
    fail_if(eet_identity_set(ef, k) != EET_ERROR_NONE);
+   eet_identity_print(k, noread);
 
    eet_close(ef);
 
@@ -1248,6 +1267,8 @@ START_TEST(eet_identity_simple)
    tmp = eet_identity_x509(ef, &size);
    fail_if(tmp == NULL);
 
+   eet_identity_certificate_print(tmp, size, noread);
+
    eet_close(ef);
 
    /* As we are changing file contain in less than 1s, this could get unnoticed
@@ -1315,7 +1336,7 @@ static int pass_get(char *pass, int size, __UNUSED__ int rwflags, __UNUSED__ voi
 {
    memset(pass, 0, size);
 
-   if (strlen("password") > size)
+   if ((int) strlen("password") > size)
      return 0;
    snprintf(pass, size, "%s", "password");
    return strlen(pass);
@@ -1325,7 +1346,7 @@ static int badpass_get(char *pass, int size, __UNUSED__ int rwflags, __UNUSED__
 {
    memset(pass, 0, size);
 
-   if (strlen("bad password") > size)
+   if ((int) strlen("bad password") > size)
      return 0;
    snprintf(pass, size, "%s", "bad password");
    return strlen(pass);
@@ -1371,7 +1392,7 @@ START_TEST(eet_cipher_decipher_simple)
 
    eet_init();
 
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
    fail_if(chdir("src/tests"));
 
    /* Crypt an eet file. */
@@ -1411,7 +1432,12 @@ START_TEST(eet_cipher_decipher_simple)
 }
 END_TEST
 
+#ifdef EFL_HAVE_THREADS
+
 static Eina_Bool open_worker_stop;
+
+# ifdef EFL_HAVE_POSIX_THREADS
+
 static void*
 open_close_worker(void* path)
 {
@@ -1433,6 +1459,31 @@ open_close_worker(void* path)
    pthread_exit(NULL);
 }
 
+# else
+
+static unsigned int __stdcall
+open_close_worker(void *path)
+{
+   while (!open_worker_stop)
+     {
+       Eet_File *ef = eet_open((char const *)path, EET_FILE_MODE_READ);
+       if (ef == NULL)
+         {
+            _endthreadex(-1);
+         }
+       else
+         {
+            Eet_Error err_code = eet_close(ef);
+            if (err_code != EET_ERROR_NONE)
+              _endthreadex(-2);
+         }
+     }
+
+   _endthreadex(0);
+}
+
+# endif
+
 START_TEST(eet_cache_concurrency)
 {
    char *file = strdup("/tmp/eet_suite_testXXXXXX");
@@ -1440,20 +1491,29 @@ START_TEST(eet_cache_concurrency)
    Eet_File *ef;
    void *thread_ret;
    unsigned int n;
+# ifdef EFL_HAVE_POSIX_THREADS
+   pthread_t thread;
+# else
+   uintptr_t thread;
+   unsigned int thread_id;
+   DWORD ret;
+# endif
 
    eet_init();
 
    /* create a file to test with */
-   fail_if(!mktemp(file));
+   fail_if(!(file = tmpnam(file)));
    ef = eet_open(file, EET_FILE_MODE_WRITE);
    fail_if(!ef);
    fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 0));
 
    /* start a thread that repeatedly opens and closes a file */
    open_worker_stop = 0;
-   pthread_t thread;
+# ifdef EFL_HAVE_POSIX_THREADS
    pthread_create(&thread, NULL, open_close_worker, file);
-
+# else
+   thread = _beginthreadex(NULL, 0, open_close_worker, file, 0, &thread_id);
+# endif
    /* clear the cache repeatedly in this thread */
    for (n = 0; n < 50000; ++n)
      {
@@ -1462,14 +1522,23 @@ START_TEST(eet_cache_concurrency)
 
    /* join the other thread, and fail if it returned an error message */
    open_worker_stop = 1;
+# ifdef EFL_HAVE_POSIX_THREADS
    fail_if(pthread_join(thread, &thread_ret) != 0);
    fail_unless(thread_ret == NULL, (char const*)thread_ret);
+# else
+   ret = WaitForSingleObject((HANDLE)thread, INFINITE);
+   fail_if(ret != WAIT_OBJECT_0);
+   fail_if(GetExitCoeThread((HANDLE)thread, &ret) == FALSE);
+   fail_if(ret != 0)
+# endif
 
    fail_if(unlink(file) != 0);
    eet_shutdown();
 }
 END_TEST
 
+#endif /* EFL_HAVE_THREADS */
+
 typedef struct _Eet_Connection_Data Eet_Connection_Data;
 struct _Eet_Connection_Data
 {
@@ -1595,6 +1664,582 @@ START_TEST(eet_connection_check)
 }
 END_TEST
 
+struct _Eet_5FP
+{
+   Eina_F32p32 fp32;
+   Eina_F16p16 fp16;
+   Eina_F8p24  fp8;
+   Eina_F32p32 f1;
+   Eina_F32p32 f0;
+};
+typedef struct _Eet_5FP Eet_5FP;
+
+struct _Eet_5DBL
+{
+   double fp32;
+   double fp16;
+   float  fp8;
+   double f1;
+   double f0;
+};
+typedef struct _Eet_5DBL Eet_5DBL;
+
+START_TEST(eet_fp)
+{
+   Eet_Data_Descriptor_Class eddc;
+   Eet_Data_Descriptor *edd_5FP;
+   Eet_Data_Descriptor *edd_5DBL;
+   Eet_5FP origin;
+   Eet_5DBL *convert;
+   Eet_5FP *build;
+   void *blob;
+   int size;
+
+   eet_init();
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_5FP);
+   edd_5FP = eet_data_descriptor_stream_new(&eddc);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp32", fp32, EET_T_F32P32);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp16", fp16, EET_T_F16P16);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp8", fp8, EET_T_F8P24);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f1", f1, EET_T_F32P32);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0", f0, EET_T_F32P32);
+
+   eet_eina_stream_data_descriptor_class_set(&eddc, "Eet_5FP", sizeof (Eet_5DBL));
+   edd_5DBL = eet_data_descriptor_stream_new(&eddc);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp16", fp16, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp8", fp8, EET_T_FLOAT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f1", f1, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f0", f0, EET_T_DOUBLE);
+
+   origin.fp32 = eina_f32p32_double_from(1.125);
+   origin.fp16 = eina_f16p16_int_from(2000);
+   origin.fp8 = eina_f8p24_int_from(125);
+   origin.f1 = eina_f32p32_int_from(1);
+   origin.f0 = 0;
+
+   blob = eet_data_descriptor_encode(edd_5FP, &origin, &size);
+   fail_if(!blob || size <= 0);
+
+   build = eet_data_descriptor_decode(edd_5FP, blob, size);
+   fail_if(!build);
+
+   convert = eet_data_descriptor_decode(edd_5DBL, blob, size);
+   fail_if(!convert);
+
+   fail_if(build->fp32 != eina_f32p32_double_from(1.125));
+   fail_if(build->fp16 != eina_f16p16_int_from(2000));
+   fail_if(build->fp8 != eina_f8p24_int_from(125));
+   fail_if(build->f1 != eina_f32p32_int_from(1));
+   fail_if(build->f0 != 0);
+
+   fail_if(convert->fp32 != 1.125);
+   fail_if(convert->fp16 != 2000);
+   fail_if(convert->fp8 != 125);
+   fail_if(convert->f1 != 1);
+   fail_if(convert->f0 != 0);
+
+   eet_shutdown();
+}
+END_TEST
+
+START_TEST(eet_file_fp)
+{
+   char *file = strdup("/tmp/eet_suite_testXXXXXX");
+   Eet_Data_Descriptor_Class eddc;
+   Eet_Data_Descriptor *edd_5FP;
+   Eet_Data_Descriptor *edd_5DBL;
+   Eet_File *ef;
+   Eet_5FP origin;
+   Eet_5DBL *convert;
+   Eet_5FP *build;
+
+   eet_init();
+
+   EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_5FP);
+   edd_5FP = eet_data_descriptor_file_new(&eddc);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp32", fp32, EET_T_F32P32);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp16", fp16, EET_T_F16P16);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp8", fp8, EET_T_F8P24);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f1", f1, EET_T_F32P32);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0", f0, EET_T_F32P32);
+
+   eet_eina_file_data_descriptor_class_set(&eddc, "Eet_5FP", sizeof (Eet_5DBL));
+   edd_5DBL = eet_data_descriptor_file_new(&eddc);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp16", fp16, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp8", fp8, EET_T_FLOAT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f1", f1, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f0", f0, EET_T_DOUBLE);
+
+   origin.fp32 = eina_f32p32_double_from(1.125);
+   origin.fp16 = eina_f16p16_int_from(2000);
+   origin.fp8 = eina_f8p24_int_from(125);
+   origin.f1 = eina_f32p32_int_from(1);
+   origin.f0 = 0;
+
+   fail_if(!(file = tmpnam(file)));
+
+   ef = eet_open(file, EET_FILE_MODE_READ_WRITE);
+   fail_if(!ef);
+
+   fail_if(!eet_data_write(ef, edd_5FP, EET_TEST_FILE_KEY1, &origin, 1));
+
+   build = eet_data_read(ef, edd_5FP, EET_TEST_FILE_KEY1);
+   fail_if(!build);
+
+   convert = eet_data_read(ef, edd_5DBL, EET_TEST_FILE_KEY1);
+   fail_if(!convert);
+
+   fail_if(build->fp32 != eina_f32p32_double_from(1.125));
+   fail_if(build->fp16 != eina_f16p16_int_from(2000));
+   fail_if(build->fp8 != eina_f8p24_int_from(125));
+   fail_if(build->f1 != eina_f32p32_int_from(1));
+   fail_if(build->f0 != 0);
+
+   fail_if(convert->fp32 != 1.125);
+   fail_if(convert->fp16 != 2000);
+   fail_if(convert->fp8 != 125);
+   fail_if(convert->f1 != 1);
+   fail_if(convert->f0 != 0);
+
+   eet_close(ef);
+
+   fail_if(unlink(file) != 0);
+
+   eet_shutdown();
+}
+END_TEST
+
+typedef struct _Eet_Union_Test Eet_Union_Test;
+typedef struct _Eet_Variant_Test Eet_Variant_Test;
+typedef struct _Eet_Variant_Type Eet_Variant_Type;
+typedef struct _Eet_Inherit_Test1 Eet_Inherit_Test1;
+typedef struct _Eet_Inherit_Test2 Eet_Inherit_Test2;
+typedef struct _Eet_Inherit_Test3 Eet_Inherit_Test3;
+typedef struct _Eet_St1 Eet_St1;
+typedef struct _Eet_St2 Eet_St2;
+typedef struct _Eet_St3 Eet_St3;
+typedef struct _Eet_List Eet_List;
+
+typedef enum _Eet_Union
+{
+  EET_UNKNOWN,
+  EET_ST1,
+  EET_ST2,
+  EET_ST3
+} Eet_Union;
+
+struct {
+   Eet_Union u;
+   const char *name;
+} eet_mapping[] = {
+  { EET_ST1, "ST1" },
+  { EET_ST2, "ST2" },
+  { EET_ST3, "ST3" },
+  { EET_UNKNOWN, NULL }
+};
+
+struct _Eet_St1
+{
+   double val1;
+   int stuff;
+   char *s1;
+};
+
+struct _Eet_St2
+{
+   Eina_Bool b1;
+   unsigned long long v1;
+};
+
+struct _Eet_St3
+{
+   int boby;
+};
+
+struct _Eet_Union_Test
+{
+   Eet_Union type;
+
+   union {
+      Eet_St1 st1;
+      Eet_St2 st2;
+      Eet_St3 st3;
+   } u;
+};
+
+struct _Eet_Variant_Type
+{
+   const char *type;
+   Eina_Bool unknow : 1;
+};
+
+struct _Eet_Variant_Test
+{
+   Eet_Variant_Type t;
+
+   void *data;
+   Eina_List *data_list;
+};
+
+struct _Eet_Inherit_Test1
+{
+   Eet_Union type;
+   Eet_St1 st1;
+};
+struct _Eet_Inherit_Test2
+{
+   Eet_Union type;
+   Eet_St2 st2;
+};
+struct _Eet_Inherit_Test3
+{
+   Eet_Union type;
+   Eet_St3 st3;
+};
+
+struct _Eet_List
+{
+   Eina_List *list;
+};
+
+static const char *
+_eet_union_type_get(const void *data, Eina_Bool *unknow)
+{
+   const Eet_Union *u = data;
+   int i;
+
+   if (unknow) *unknow = EINA_FALSE;
+   for (i = 0; eet_mapping[i].name != NULL; ++i)
+     if (*u == eet_mapping[i].u)
+       return eet_mapping[i].name;
+
+   if (unknow) *unknow = EINA_TRUE;
+   return NULL;
+}
+
+static Eina_Bool
+_eet_union_type_set(const char *type, void *data, Eina_Bool unknow)
+{
+   Eet_Union *u = data;
+   int i;
+
+   if (unknow) return EINA_FALSE;
+
+   for (i = 0; eet_mapping[i].name != NULL; ++i)
+     if (strcmp(eet_mapping[i].name, type) == 0)
+       {
+         *u = eet_mapping[i].u;
+         return EINA_TRUE;
+       }
+
+   return EINA_FALSE;
+}
+
+static const char *
+_eet_variant_type_get(const void *data, Eina_Bool *unknow)
+{
+   const Eet_Variant_Type *type = data;
+   int i;
+
+   if (unknow) *unknow = type->unknow;
+   for (i = 0; eet_mapping[i].name != NULL; ++i)
+     if (strcmp(type->type, eet_mapping[i].name) == 0)
+       return eet_mapping[i].name;
+
+   if (unknow) *unknow = EINA_FALSE;
+   return type->type;
+}
+
+static Eina_Bool
+_eet_variant_type_set(const char *type, void *data, Eina_Bool unknow)
+{
+   Eet_Variant_Type *vt = data;
+
+   vt->type = type;
+   vt->unknow = unknow;
+   return EINA_TRUE;
+}
+
+static Eet_Data_Descriptor*
+_eet_st1_dd(void)
+{
+   Eet_Data_Descriptor_Class eddc;
+   Eet_Data_Descriptor *res;
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St1);
+   res = eet_data_descriptor_stream_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "val1", val1, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "stuff", stuff, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "s1", s1, EET_T_STRING);
+
+   return res;
+}
+
+static void
+_eet_st1_set(Eet_St1 *st1, int i)
+{
+   st1->val1 = EET_TEST_DOUBLE;
+   st1->stuff = EET_TEST_INT + i;
+   st1->s1 = EET_TEST_STRING;
+}
+
+static void
+_eet_st1_cmp(Eet_St1 *st1, int i)
+{
+   double tmp;
+
+   fail_if(!st1);
+
+   tmp = st1->val1 - EET_TEST_DOUBLE;
+   if (tmp < 0) tmp = -tmp;
+   fail_if(tmp > 0.005);
+   fail_if(st1->stuff != EET_TEST_INT + i);
+   fail_if(strcmp(st1->s1, EET_TEST_STRING));
+}
+
+static Eet_Data_Descriptor*
+_eet_st2_dd(void)
+{
+   Eet_Data_Descriptor_Class eddc;
+   Eet_Data_Descriptor *res;
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St2);
+   res = eet_data_descriptor_stream_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St2, "b1", b1, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St2, "v1", v1, EET_T_ULONG_LONG);
+
+   return res;
+}
+
+static void
+_eet_st2_set(Eet_St2 *st2, int i)
+{
+   st2->b1 = EINA_TRUE;
+   st2->v1 = EET_TEST_LONG_LONG + i;
+}
+
+static void
+_eet_st2_cmp(Eet_St2 *st2, int i)
+{
+   fail_if(!st2->b1);
+   fail_if(st2->v1 != EET_TEST_LONG_LONG + i);
+}
+
+static Eet_Data_Descriptor*
+_eet_st3_dd(void)
+{
+   Eet_Data_Descriptor_Class eddc;
+   Eet_Data_Descriptor *res;
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St3);
+   res = eet_data_descriptor_stream_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St3, "boby", boby, EET_T_INT);
+
+   return res;
+}
+
+static void
+_eet_st3_set(Eet_St3 *st3, int i)
+{
+   st3->boby = EET_TEST_INT + i;
+}
+
+static void
+_eet_st3_cmp(Eet_St3 *st3, int i)
+{
+   fail_if(st3->boby != EET_TEST_INT + i);
+}
+
+START_TEST(eet_test_union)
+{
+   Eet_Union_Test *eut;
+   Eet_List *l;
+   Eet_Data_Descriptor_Class eddc;
+   Eet_Data_Descriptor *edd;
+   Eet_Data_Descriptor *unified;
+   Eet_Data_Descriptor *m;
+   void *blob;
+   int size;
+   int i;
+
+   eina_init();
+   eet_init();
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Union_Test);
+   edd = eet_data_descriptor_stream_new(&eddc);
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Union_Test);
+   m = eet_data_descriptor_stream_new(&eddc);
+
+   eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
+   eddc.func.type_get = _eet_union_type_get;
+   eddc.func.type_set = _eet_union_type_set;
+   unified = eet_data_descriptor_stream_new(&eddc);
+
+   EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST1", _eet_st1_dd());
+   EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST2", _eet_st2_dd());
+   EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST3", _eet_st3_dd());
+
+   EET_DATA_DESCRIPTOR_ADD_UNION(edd, Eet_Union_Test, "u", u, type, unified);
+
+   EET_DATA_DESCRIPTOR_ADD_LIST(m, Eet_List, "list", list, edd);
+
+   l = calloc(1, sizeof (Eet_List));
+
+#define EUT_NEW(Type_Index)                    \
+   eut = calloc(1, sizeof (Eet_Union_Test));   \
+   eut->type = EET_ST##Type_Index;             \
+   _eet_st##Type_Index##_set(&(eut->u.st##Type_Index), i);
+
+   for (i = 0; i < 3; ++i)
+     {
+       EUT_NEW(1);
+       l->list = eina_list_append(l->list, eut);
+
+       EUT_NEW(2);
+       l->list = eina_list_append(l->list, eut);
+
+       EUT_NEW(3);
+       l->list = eina_list_append(l->list, eut);
+     }
+
+   blob = eet_data_descriptor_encode(m, l, &size);
+   fail_if(!blob || size <= 0);
+
+   l = eet_data_descriptor_decode(m, blob, size);
+   fail_if(!l);
+
+   fail_if(eina_list_count(l->list) != 9);
+
+#define EUT_CMP(Type_Index)                                    \
+   eut = eina_list_nth(l->list, i * 3 + Type_Index - 1);       \
+   fail_if(eut->type != EET_ST##Type_Index);                   \
+   _eet_st##Type_Index##_cmp(&(eut->u.st##Type_Index), i);
+
+   for (i = 0; i < 3; ++i)
+     {
+       EUT_CMP(1);
+       EUT_CMP(2);
+       EUT_CMP(3);
+     }
+
+   eet_shutdown();
+   eina_shutdown();
+}
+END_TEST
+
+START_TEST(eet_test_variant)
+{
+   Eet_Variant_Test *evt;
+   Eet_List *l;
+   Eet_St1 *st1;
+   Eet_St2 *st2;
+   Eet_St3 *st3;
+   Eet_Data_Descriptor_Class eddc;
+   Eet_Data_Descriptor *edd;
+   Eet_Data_Descriptor *unified;
+   Eet_Data_Descriptor *m;
+   void *blob;
+   int size;
+   int i;
+
+   eina_init();
+   eet_init();
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Variant_Test);
+   edd = eet_data_descriptor_stream_new(&eddc);
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Variant_Test);
+   m = eet_data_descriptor_stream_new(&eddc);
+
+   eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
+   eddc.func.type_get = _eet_variant_type_get;
+   eddc.func.type_set = _eet_variant_type_set;
+   unified = eet_data_descriptor_stream_new(&eddc);
+
+   EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST1", _eet_st1_dd());
+   EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST2", _eet_st2_dd());
+   EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST3", _eet_st3_dd());
+
+   EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, Eet_Variant_Test, "data", data, t, unified);
+
+   unified = eet_data_descriptor_stream_new(&eddc);
+   eet_data_descriptor_element_add(unified, "ST1",
+                                  EET_T_UNKNOW, EET_G_LIST,
+                                  0, 0, NULL, _eet_st1_dd());
+   eet_data_descriptor_element_add(unified, "ST2",
+                                  EET_T_UNKNOW, EET_G_LIST,
+                                  0, 0, NULL, _eet_st2_dd());
+
+   EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, Eet_Variant_Test,
+                                  "data_list", data_list, t, unified);
+
+   EET_DATA_DESCRIPTOR_ADD_LIST(m, Eet_List, "list", list, edd);
+
+   l = calloc(1, sizeof (Eet_List));
+
+#define EVT_NEW(Type_Index)                                    \
+   evt = calloc(1, sizeof (Eet_Variant_Test));                 \
+   evt->t.type = eet_mapping[Type_Index - 1].name;             \
+   st##Type_Index = calloc(1, sizeof (Eet_St##Type_Index));    \
+   _eet_st##Type_Index##_set(st##Type_Index, i);               \
+   evt->data = st##Type_Index;
+
+   for (i = 0; i < 3; ++i)
+     {
+       EVT_NEW(1);
+       l->list = eina_list_append(l->list, evt);
+
+       st1 = calloc(1, sizeof (Eet_St1));
+       _eet_st1_set(st1, i);
+       evt->data_list = eina_list_append(evt->data_list, st1);
+
+       EVT_NEW(2);
+       l->list = eina_list_append(l->list, evt);
+
+       EVT_NEW(3);
+       l->list = eina_list_append(l->list, evt);
+     }
+
+   blob = eet_data_descriptor_encode(m, l, &size);
+   fail_if(!blob || size <= 0);
+
+   l = eet_data_descriptor_decode(m, blob, size);
+   fail_if(!l);
+
+   fail_if(eina_list_count(l->list) != 9);
+
+#define EVT_CMP(Type_Index)                                            \
+   evt = eina_list_nth(l->list, i * 3 + Type_Index - 1);               \
+   fail_if(strcmp(evt->t.type, eet_mapping[Type_Index - 1].name) != 0);        \
+   _eet_st##Type_Index##_cmp(evt->data, i);
+
+   for (i = 0; i < 3; ++i)
+     {
+       EVT_CMP(1);
+
+       fail_if(!evt->data_list);
+       fail_if(eina_list_count(evt->data_list) != 1);
+
+       st1 = eina_list_data_get(evt->data_list);
+       _eet_st1_cmp(st1, i);
+
+       EVT_CMP(2);
+       EVT_CMP(3);
+     }
+
+   eet_shutdown();
+   eina_shutdown();
+}
+END_TEST
+
 Suite *
 eet_suite(void)
 {
@@ -1611,12 +2256,16 @@ eet_suite(void)
    tcase_add_test(tc, eet_test_basic_data_type_encoding_decoding);
    tcase_add_test(tc, eet_test_data_type_encoding_decoding);
    tcase_add_test(tc, eet_test_data_type_dump_undump);
+   tcase_add_test(tc, eet_fp);
+   tcase_add_test(tc, eet_test_union);
+   tcase_add_test(tc, eet_test_variant);
    suite_add_tcase(s, tc);
 
    tc = tcase_create("Eet File");
    tcase_add_test(tc, eet_file_simple_write);
    tcase_add_test(tc, eet_file_data_test);
    tcase_add_test(tc, eet_file_data_dump_test);
+   tcase_add_test(tc, eet_file_fp);
    suite_add_tcase(s, tc);
 
    tc = tcase_create("Eet Image");
@@ -1639,9 +2288,11 @@ eet_suite(void)
    suite_add_tcase(s, tc);
 #endif
 
+#ifdef EFL_HAVE_THREADS
    tc = tcase_create("Eet Cache");
    tcase_add_test(tc, eet_cache_concurrency);
    suite_add_tcase(s, tc);
+#endif
 
    tc = tcase_create("Eet Connection");
    tcase_add_test(tc, eet_connection_check);