| /** | |
| * 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(); | |
| } | |