blob: 01fc3bd670b96b1e9bf20e0e3c136a90610d18d4 [file]
/**
* test_objects.c -- test etch_objects
*/
#include <tchar.h>
#include <stdio.h>
#include <conio.h>
#include "cunit.h"
#include "basic.h"
#include "automated.h"
#include "etch_global.h"
#include "etch_objects.h"
#include "etch_arraylist.h"
#ifndef TESTSUITEDEFS
#define TESTSUITEDEFS
int init_suite(void)
{
return etch_runtime_init();
}
int clean_suite(void)
{
return etch_runtime_cleanup(0,0); /* free memtable and cache etc */
}
int g_is_automated_test, g_bytes_allocated;
#define IS_DEBUG_CONSOLE FALSE
#endif /* TESTSUITEDEFS */
#define OBJSIG 0xbadf00d
#define NUMITEMS 3
#define ETCHTYPEA_TESTOBJ 0xff
/**
* globals, test objects to stuff into arraylists, etc
*/
int bytes_allocated, bytes_prior;
typedef struct TESTOBJ
{ int id;
int signature;
} TESTOBJ;
TESTOBJ* objfactory(const int id)
{
TESTOBJ* obj = etch_malloc(sizeof(TESTOBJ), ETCHTYPEA_TESTOBJ);
obj->id = id; obj->signature = OBJSIG;
return obj;
}
/**
* comparator callback for contains(), indexof(), functions
* typedef int (*etch_comparator) (void* myobj, void* otherobj);
*/
int al_comparator(void* p, void* q)
{
int result = 0;
TESTOBJ* myobj = (TESTOBJ*)p, *othobj = (TESTOBJ*)q;
if (!myobj || !othobj) result = -2;
else if (myobj->signature != OBJSIG || othobj->signature != OBJSIG) result = -2;
else if (myobj->id < othobj->id) result = -1;
else if (myobj->id > othobj->id) result = 1;
else result = 0; /* equality */
return result;
}
/*
* test ETCH_INT32 object
*/
void test_int32(void)
{
void* pvtbl = NULL;
const int testval = -1;
ETCH_INT32* newobj = new_etch_int32(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, sizeof(int));
CU_ASSERT_EQUAL(newobj->value_int32, testval);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_INT32);
CU_ASSERT_PTR_NULL(newobj->result);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_INT64 object
*/
void test_int64(void)
{
void* pvtbl = NULL;
const short testval = -1;
ETCH_INT64* newobj = new_etch_int64(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, sizeof(int64));
CU_ASSERT_EQUAL(newobj->value_int64, -1);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_INT64);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_INT16 object
*/
void test_int16(void)
{
void* pvtbl = NULL;
const short testval = -1;
ETCH_INT16* newobj = new_etch_int16(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, sizeof(short));
CU_ASSERT_EQUAL(newobj->value_int16, -1);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_INT16);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_INT8 object
*/
void test_int8(void)
{
void* pvtbl = NULL;
const signed char testval = -1;
ETCH_INT8* newobj = new_etch_int8(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, sizeof(char));
CU_ASSERT_EQUAL(newobj->value_int8, -1);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_INT8);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_BOOL object
*/
void test_bool(void)
{
void* pvtbl = NULL;
const unsigned char testval = 0x11;
ETCH_BOOL* newobj = new_etch_bool(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, sizeof(char));
CU_ASSERT_EQUAL(newobj->value_int8, TRUE);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_BOOL);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_IEEE64 object
*/
void test_ieee64(void)
{
void* pvtbl = NULL;
const double testval = 3.14159;
ETCH_IEEE64* newobj = new_etch_ieee64(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, sizeof(double));
CU_ASSERT_DOUBLE_EQUAL(newobj->value_ieee64, testval, (double)0.00001);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_IEEE64);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_IEEE32 object
*/
void test_ieee32(void)
{
void* pvtbl = NULL;
const float testval = (float)3.14159;
ETCH_IEEE32* newobj = new_etch_ieee32(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, sizeof(float));
CU_ASSERT_DOUBLE_EQUAL(newobj->value_ieee32, testval, (float)0.00001);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_IEEE32);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_STRING object
*/
void test_string(void)
{
void* pvtbl = NULL;
ETCH_STRING* newobj = NULL;
const wchar_t* teststr = L"it works!";
size_t testlen = (wcslen(teststr) + 1) * sizeof(wchar_t);
wchar_t* testval = etch_malloc(testlen, 0);
memcpy(testval, teststr, testlen);
/* cache_dump(); */
/* note that cache is not clear, should not re-cache here - check cache.find() */
newobj = new_etch_string(testval);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
/* TODO: figure out what's wrong with these tests. we know the vtable is OK
* since desttroy() works fine thru the vtable, below.
* CU_ASSERT_EQUAL_FATAL(newobj->vtab, pvtbl);
* CU_ASSERT_EQUAL_FATAL(newobj->vtab->destroy, destroy_etchobject);
*/
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->size, testlen);
CU_ASSERT_EQUAL(memcmp(newobj->value_ptr_to, teststr, testlen), 0);
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_STRING);
CU_ASSERT_PTR_NULL(newobj->result);
/* ensure object memory is destroyed as expected */
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/*
* test ETCH_ARRAYLIST object
* TODO: much more comprehensive test of boxed arraylists: clone, etc.
* TODO: write custom ctor with dedicated vtable for this object type
* that permits the object to be destroyed with or without freeing
* memory for the list contents. when we do this, remove the code
* in etchobject destroy and clone methods which do this.
*/
void test_arraylist(void)
{
void* pvtbl = NULL;
etch_arraylist* list = NULL;
TESTOBJ* t1 = NULL, *t2 = NULL;
const int initsize = 8, deltsize = 4, NOTREADONLY = FALSE;
ETCH_ARRAYLIST* newobj = NULL;
newobj = new_etch_arraylist(initsize,deltsize,NOTREADONLY);
/* ensure the etchobject and its interface were created */
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->vtab);
CU_ASSERT_PTR_NOT_NULL_FATAL(newobj->value_ptr_to);
/* ensure the i_etchobject vtable is cached and is correct */
pvtbl = cache_find(ETCHTYPE_VTABLE_ETCHOBJECT, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(pvtbl);
/* ensure object instance data is as expected */
CU_ASSERT_EQUAL(newobj->type, ETCHTYPE_BOXED_ARRAYLIST);
/* allocate content memory and add content to arraylist */
list = newobj->value_ptr_to;
arraylist_add(list, t1 = objfactory(1));
arraylist_add(list, t2 = objfactory(2));
CU_ASSERT_EQUAL(list->count, 2);
/* ensure object memory is destroyed as expected. since we specified
* false for is_readonly in the new_etch_arraylist constructor, any
* memory allocated for arraylist content *will* be freed in destroy().
* of course we should eventually test with is_readonly true, and
* ensuring memory remains allocated.
*/
newobj->vtab->destroy(newobj);
bytes_allocated = etch_showmem(TRUE,FALSE);
CU_ASSERT_EQUAL(bytes_allocated, 0);
memtable_clear(); /* start fresh for next test */
}
/**
* main
*/
int _tmain(int argc, _TCHAR* argv[])
{
char c=0;
CU_pSuite pSuite = NULL;
g_is_automated_test = argc > 1 && 0 != wcscmp(argv[1], L"-a");
if (CUE_SUCCESS != CU_initialize_registry()) return 0;
CU_set_output_filename("../test_etchobjects");
pSuite = CU_add_suite("suite_etchobjects", init_suite, clean_suite);
CU_add_test(pSuite, "test ETCH_INT32", test_int32);
CU_add_test(pSuite, "test ETCH_INT64", test_int64);
CU_add_test(pSuite, "test ETCH_INT16", test_int16);
CU_add_test(pSuite, "test ETCH_INT8", test_int8);
CU_add_test(pSuite, "test ETCH_BOOL", test_bool);
CU_add_test(pSuite, "test ETCH_IEEE64", test_ieee64);
CU_add_test(pSuite, "test ETCH_IEEE32", test_ieee32);
CU_add_test(pSuite, "test ETCH_STRING", test_string);
CU_add_test(pSuite, "test ETCH_ARRAYLIST", test_arraylist);
if (g_is_automated_test)
CU_automated_run_tests();
else
{ CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
}
if (!g_is_automated_test) { printf("any key ..."); while(!c) c = _getch(); wprintf(L"\n"); }
CU_cleanup_registry();
return CU_get_error();
}