You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@etch.apache.org by jd...@apache.org on 2009/04/22 19:25:51 UTC
svn commit: r767594 [22/43] - in /incubator/etch/trunk/binding-c/runtime/c:
./ ext/ ext/hashtab/ ext/lib/ inc/ lib/ project/ project/$etchstop/
project/bin/ project/etch/ project/logcli/ project/logsrv/ project/notes/
project/test/ project/test/logcli/...
Added: incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_arraylist.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_arraylist.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_arraylist.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_arraylist.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,693 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * test_arraylist.c -- test etch_arraylist
+ */
+#include "apr_time.h" /* some apr must be included first */
+#include "etchthread.h"
+#include <tchar.h>
+#include <stdio.h>
+#include <conio.h>
+
+#include "cunit.h"
+#include "basic.h"
+#include "automated.h"
+
+#include "etch_global.h"
+#include "etch_arraylist.h"
+
+#define OBJSIG 0xbadf00d
+#define NUMITEMS 3
+#define ETCHTYPEA_TESTOBJ 0xff
+
+
+int apr_setup(void);
+int apr_teardown(void);
+int this_setup();
+int this_teardown();
+apr_pool_t* g_apr_mempool;
+const char* pooltag = "etchpool";
+
+
+/* - - - - - - - - - - - - - -
+ * unit test infrastructure
+ * - - - - - - - - - - - - - -
+ */
+
+int init_suite(void)
+{
+ apr_setup();
+ etch_runtime_init(TRUE);
+ return this_setup();
+}
+
+int clean_suite(void)
+{
+ this_teardown();
+ etch_runtime_cleanup(0,0); /* free memtable and cache etc */
+ apr_teardown();
+ return 0;
+}
+
+int g_is_automated_test, g_bytes_allocated;
+
+#define IS_DEBUG_CONSOLE FALSE
+
+/*
+ * apr_setup()
+ * establish apache portable runtime environment
+ */
+int apr_setup(void)
+{
+ int result = apr_initialize();
+ if (result == 0)
+ { result = etch_apr_init();
+ g_apr_mempool = etch_apr_mempool;
+ }
+ if (g_apr_mempool)
+ apr_pool_tag(g_apr_mempool, pooltag);
+ else result = -1;
+ return result;
+}
+
+/*
+ * apr_teardown()
+ * free apache portable runtime environment
+ */
+int apr_teardown(void)
+{
+ if (g_apr_mempool)
+ apr_pool_destroy(g_apr_mempool);
+ g_apr_mempool = NULL;
+ apr_terminate();
+ return 0;
+}
+
+int this_setup()
+{
+ etch_apr_mempool = g_apr_mempool;
+ return 0;
+}
+
+int this_teardown()
+{
+ return 0;
+}
+
+int 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 new_arraylist()
+ */
+void test_new_arraylist(void)
+{
+ const int TESTSIZE = 2048, TESTDELTA = 1024;
+
+ etch_arraylist* list = new_arraylist(0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(list);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(list->base);
+ CU_ASSERT_EQUAL(list->count,0);
+ CU_ASSERT_EQUAL(list->size, ETCHARRAYLIST_DEFSIZE * sizeof(void**));
+ CU_ASSERT_EQUAL(list->delta, ETCHARRAYLIST_DEFSIZE * sizeof(void**));
+
+ arraylist_destroy(list,TRUE); /* free memory and ensure nothing remains allocated */
+ g_bytes_allocated = etch_showmem(TRUE,FALSE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+
+ list = new_arraylist(TESTSIZE, TESTDELTA);
+ CU_ASSERT_EQUAL(list->count,0);
+ CU_ASSERT_EQUAL(list->size, TESTSIZE * sizeof(void**));
+ CU_ASSERT_EQUAL(list->delta, TESTDELTA * sizeof(void**));
+ memset(list->base, 0xff, list->size); /* try write to entire buffer */
+
+ arraylist_destroy(list,TRUE); /* free memory; ensure nothing remains allocated */
+ g_bytes_allocated = etch_showmem(TRUE,FALSE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_add()
+ */
+void test_add(void)
+{
+ TESTOBJ *x1, *x2;
+ etch_arraylist* list = new_arraylist(8,0);
+ CU_ASSERT_EQUAL(list->base[0],NULL);
+ CU_ASSERT_EQUAL(list->base[1],NULL);
+
+ arraylist_add(list, x1 = objfactory(1));
+ CU_ASSERT_EQUAL(list->count,1);
+ CU_ASSERT_EQUAL(list->base[0], x1); /* ensure item's buffer slot OK */
+
+ arraylist_add(list, x2 = objfactory(2));
+ CU_ASSERT_EQUAL(list->count,2);
+ CU_ASSERT_EQUAL(list->base[1], x2); /* ensure item's buffer slot OK */
+
+ arraylist_destroy(list,TRUE); /* free memory including test objects */
+ g_bytes_allocated = etch_showmem(TRUE,FALSE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_destroy()
+ */
+void test_destroy(void)
+{
+ CU_PASS("tested in all previous and subsequent tests");
+}
+
+
+/*
+ * test arraylist_remove()
+ */
+void test_remove_firstitem(void)
+{
+ TESTOBJ *x1, *x2;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x1 = objfactory(1)); /* allocate and add test obj x1 */
+ arraylist_add(list, x2 = objfactory(2)); /* allocate and add test obj x2 */
+
+ CU_ASSERT_EQUAL_FATAL(list->count,2);
+ CU_ASSERT_EQUAL(list->base[0], x1);
+ CU_ASSERT_EQUAL(list->base[1], x2);
+ bytes_prior = etch_showmem(0,0);
+
+ arraylist_remove(list,0,TRUE); /* remove list[0] and free its x1 memory */
+
+ CU_ASSERT_EQUAL_FATAL(list->count,1);
+ g_bytes_allocated = etch_showmem(0,0); /* ensure TESTBOJ bytes were freed */
+ CU_ASSERT_EQUAL(bytes_prior - g_bytes_allocated, sizeof(TESTOBJ));
+ CU_ASSERT_EQUAL(list->base[1], NULL); /* ensure item's buffer slot cleared */
+
+ CU_ASSERT_EQUAL_FATAL(list->base[0], x2); /* ensure item 1 is now item 0 */
+
+ arraylist_remove(list,0,FALSE); /* remove list[0] but don't free x2 memory */
+
+ bytes_prior = etch_showmem(0,0);
+ CU_ASSERT_EQUAL(list->count,0); /* ensure no bytes were freed */
+ CU_ASSERT_EQUAL(bytes_prior, g_bytes_allocated);
+ CU_ASSERT_EQUAL(list->base[0], NULL); /* ensure item's buffer slot cleared */
+
+ /* finally free the last test object, which would have been freed in the
+ * prior arraylist_remove() had we not specified to not do so. Also if we
+ * did not free it here it would be freed in the memtable_clear() below.
+ */
+ etch_free(x2);
+
+ arraylist_destroy(list,TRUE); /* destroy the arraylist */
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_remove()
+ */
+void test_remove_lastitem(void)
+{
+ TESTOBJ *x1, *x2, *x3;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x1 = objfactory(1)); /* allocate and add test obj x1 */
+ arraylist_add(list, x2 = objfactory(2)); /* allocate and add test obj x2 */
+ arraylist_add(list, x3 = objfactory(3)); /* allocate and add test obj x3 */
+ CU_ASSERT_EQUAL_FATAL(list->count,3);
+
+ CU_ASSERT_EQUAL(list->base[2], x3);
+
+ arraylist_remove(list,2,TRUE); /* remove list[2] and free its x1 memory */
+
+ CU_ASSERT_EQUAL(list->base[2], NULL); /* ensure item's buffer slot cleared */
+
+ CU_ASSERT_EQUAL_FATAL(list->base[0], x1);
+ CU_ASSERT_EQUAL_FATAL(list->base[1], x2);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+void dumplist(etch_arraylist* list)
+{
+ int i=0; char c=0;
+ const int n = list->count;
+ printf("\ndumping list ...\n"); fflush(stdout);
+ for(; i < n; i++)
+ { TESTOBJ* item = list->base[i];
+ printf("\n list[%d] %d\n", i, item->id); fflush(stdout);
+ }
+
+ printf("\nany key ..."); while(!c) c = _getch(); printf("\n");
+}
+
+
+/*
+ * removetest_comparator()
+ * comparator for test_remove() arraylist_indexof
+ * note that the test value is passed as an int not an object
+ */
+int removetest_comparator(void* testvalue, void* listcontent)
+{
+ const int ivalue = (int) (size_t) testvalue;
+ TESTOBJ* listobj = (TESTOBJ*) listcontent;
+ int jvalue = listobj->id;
+ return ivalue < jvalue? -1: ivalue > jvalue? 1: 0;
+}
+
+
+/*
+ * test_remove()
+ * remove items
+ */
+void test_remove(void)
+{
+ const int numitems = 10;
+ int i=0, curritems = numitems;
+ etch_arraylist* list = new_arraylist(64,0);
+
+ for(; i < numitems; i++)
+ arraylist_add(list, objfactory(i));
+
+ #if IS_DEBUG_CONSOLE
+ dumplist(list);
+ #endif
+
+ for(i=2; i < numitems; i+=2)
+ {
+ /* remove the list content whose value is i */
+ const int index = arraylist_indexof(list, (void*)(size_t) i, 0, removetest_comparator);
+ CU_ASSERT_NOT_EQUAL(index, -1);
+
+ if (index >= 0)
+ {
+ if (0 == arraylist_remove(list, index, TRUE))
+ curritems--;
+
+ #if IS_DEBUG_CONSOLE
+ dumplist(list);
+ #endif
+ }
+ else
+ {
+ #if IS_DEBUG_CONSOLE
+ printf("could not remove list content %d\n", i);
+ #endif
+ }
+
+ CU_ASSERT_EQUAL(list->count, curritems);
+ }
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_insert()
+ */
+void test_insert_first(void)
+{
+ TESTOBJ *x1, *x2, *x3;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x2 = objfactory(2)); /* allocate and add test obj x2 */
+ arraylist_add(list, x3 = objfactory(3)); /* allocate and add test obj x3 */
+
+ /* insert test obj x1 into slot 0 */
+ arraylist_insert(list, 0, x1 = objfactory(1));
+
+ CU_ASSERT_EQUAL_FATAL(list->count,3);
+ CU_ASSERT_EQUAL(list->base[0], x1);
+ CU_ASSERT_EQUAL(list->base[1], x2);
+ CU_ASSERT_EQUAL(list->base[2], x3);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_insert()
+ */
+void test_insert_mid(void)
+{
+ TESTOBJ *x1, *x2, *x3;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x1 = objfactory(1));
+ arraylist_add(list, x3 = objfactory(3));
+
+ /* insert test obj x1 into slot 1 */
+ arraylist_insert(list, 1, x2 = objfactory(2));
+
+ CU_ASSERT_EQUAL_FATAL(list->count,3);
+ CU_ASSERT_EQUAL(list->base[0], x1);
+ CU_ASSERT_EQUAL(list->base[1], x2);
+ CU_ASSERT_EQUAL(list->base[2], x3);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_insert()
+ */
+void test_insert_end(void)
+{
+ TESTOBJ *x1, *x2, *x3;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x1 = objfactory(1));
+ arraylist_add(list, x2 = objfactory(2));
+
+ /* insert test obj x1 into slot 1 */
+ arraylist_insert(list, 2, x3 = objfactory(3));
+
+ CU_ASSERT_EQUAL_FATAL(list->count,3);
+ CU_ASSERT_EQUAL(list->base[0], x1);
+ CU_ASSERT_EQUAL(list->base[1], x2);
+ CU_ASSERT_EQUAL(list->base[2], x3);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_containsp(), arraylist_contains()
+ */
+void test_contains(void)
+{
+ TESTOBJ *x1, *x2, *x3;
+ int result = 0;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x1 = objfactory(1));
+ arraylist_add(list, x2 = objfactory(2));
+ arraylist_add(list, x3 = objfactory(3));
+
+ result = arraylist_containsp(list, x1, 0);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ result = arraylist_containsp(list, x2, 0);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ result = arraylist_containsp(list, x3, 0);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ result = arraylist_containsp(list, x1, 1); /* start at index 1 */
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ result = arraylist_contains(list, x1, 0, al_comparator);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ result = arraylist_contains(list, x2, 0, al_comparator);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ result = arraylist_contains(list, x3, 0, al_comparator);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ result = arraylist_contains(list, x1, 2, al_comparator); /* start at index 2 */
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+/*
+ * test arraylist_indexofp(), arraylist_indexof()
+ */
+void test_indexof(void)
+{
+ TESTOBJ *x1, *x2, *x3;
+ int result = 0;
+ etch_arraylist* list = new_arraylist(8,0);
+ x3 = objfactory(3);
+
+ arraylist_add(list, x1 = objfactory(1));
+ arraylist_add(list, x2 = objfactory(2));
+
+ result = arraylist_indexofp(list, x1, 0);
+ CU_ASSERT_EQUAL(result, 0);
+
+ result = arraylist_indexofp(list, x2, 0);
+ CU_ASSERT_EQUAL(result, 1);
+
+ result = arraylist_indexofp(list, x3, 0);
+ CU_ASSERT_EQUAL(result, -1); /* not found */
+
+ result = arraylist_indexofp(list, x1, 1); /* start at index 1 */
+ CU_ASSERT_EQUAL(result, -1);
+
+ result = arraylist_indexof(list, x1, 0, al_comparator);
+ CU_ASSERT_EQUAL(result, 0);
+
+ result = arraylist_indexof(list, x2, 0, al_comparator);
+ CU_ASSERT_EQUAL(result, 1);
+
+ result = arraylist_indexof(list, x3, 0, al_comparator);
+ CU_ASSERT_EQUAL(result, -1);
+
+ result = arraylist_indexof(list, x1, 1, al_comparator);
+ CU_ASSERT_EQUAL(result, -1);
+
+ etch_free(x3);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_get()
+ */
+void test_get(void)
+{
+ TESTOBJ *x1, *x2, *x3, *x;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x1 = objfactory(1));
+ arraylist_add(list, x2 = objfactory(2));
+ arraylist_add(list, x3 = objfactory(3));
+
+ x = arraylist_get(list,0);
+ CU_ASSERT_EQUAL(x, x1);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->signature, OBJSIG);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->id, 1);
+
+ x = arraylist_get(list,1);
+ CU_ASSERT_EQUAL(x, x2);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->signature, OBJSIG);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->id, 2);
+
+ x = arraylist_get(list,2);
+ CU_ASSERT_EQUAL(x, x3);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->signature, OBJSIG);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->id, 3);
+
+ x = arraylist_get(list,3);
+ CU_ASSERT_EQUAL(x, NULL);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist_set()
+ */
+void test_set(void)
+{
+ int result = 0;
+ TESTOBJ *x1, *x2, *x3, *x4, *x5;
+ etch_arraylist* list = new_arraylist(8,0);
+
+ arraylist_add(list, x1 = objfactory(1));
+ arraylist_add(list, x2 = objfactory(2));
+ arraylist_add(list, x3 = objfactory(3));
+
+ result = arraylist_set(list, 0, x4 = objfactory(4));
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_EQUAL(list->base[0], x4);
+
+ result = arraylist_set(list, 2, x5 = objfactory(5));
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_EQUAL(list->base[2], x5);
+
+ result = arraylist_set(list, 3, x5); /* attempt replace beyond end of list */
+ CU_ASSERT_EQUAL(result,-1);
+
+ /* destroy the arraylist without freeing the test object content */
+ arraylist_destroy(list,FALSE);
+
+ etch_free(x1); etch_free(x2); etch_free(x3); etch_free(x4); etch_free(x5);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/*
+ * test arraylist auto reallocation
+ */
+void test_expand(void)
+{
+ const int INIT_MAX = 4;
+ TESTOBJ *x1, *x2, *x3, *x4, *x5, *x6, *x;
+ etch_arraylist* list = new_arraylist(INIT_MAX,0);
+
+ arraylist_add(list, x1 = objfactory(1));
+ arraylist_add(list, x2 = objfactory(2));
+ arraylist_add(list, x3 = objfactory(3));
+ arraylist_add(list, x4 = objfactory(4));
+ CU_ASSERT_EQUAL(list->size, INIT_MAX * sizeof(void**));
+
+ arraylist_add(list, x5 = objfactory(5));
+ CU_ASSERT_EQUAL(list->size, INIT_MAX * sizeof(void**) * 2);
+ arraylist_add(list, x6 = objfactory(6));
+
+ x = arraylist_get(list,4);
+ CU_ASSERT_EQUAL(x, x5);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->signature, OBJSIG);
+ CU_ASSERT_EQUAL(((TESTOBJ*)x)->id, 5);
+ x = arraylist_get(list,5);
+ CU_ASSERT_EQUAL(x, x6);
+
+ /* destroy the arraylist freeing the test object content as well */
+ arraylist_destroy(list,TRUE);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_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_arraylist");
+
+ pSuite = CU_add_suite("suite_arraylist", init_suite, clean_suite);
+
+ CU_add_test(pSuite, "test new_arraylist()", test_new_arraylist);
+ CU_add_test(pSuite, "test arraylist_add()", test_add);
+ CU_add_test(pSuite, "test arraylist_destroy()", test_destroy);
+ CU_add_test(pSuite, "test arraylist_remove() first", test_remove_firstitem);
+ CU_add_test(pSuite, "test arraylist_remove() last", test_remove_lastitem);
+ CU_add_test(pSuite, "test arraylist_remove() mid", test_remove);
+ CU_add_test(pSuite, "test arraylist_insert() first", test_insert_first);
+ CU_add_test(pSuite, "test arraylist_insert() mid", test_insert_mid);
+ CU_add_test(pSuite, "test arraylist_insert() end", test_insert_end);
+ CU_add_test(pSuite, "test arraylist_contains(), containsp", test_contains);
+ CU_add_test(pSuite, "test arraylist_indexof(), indexofp", test_indexof);
+ CU_add_test(pSuite, "test arraylist_get()", test_get);
+ CU_add_test(pSuite, "test arraylist set", test_set);
+ CU_add_test(pSuite, "test arraylist auto realloc", test_expand);
+
+ 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();
+}
+
Added: incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_assignment.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_assignment.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_assignment.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_assignment.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,1071 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * test_assignment.c -- test etch object assignability and assignment
+ */
+#include "apr_time.h" /* some apr must be included first */
+#include "etchthread.h"
+#include <tchar.h>
+#include <stdio.h>
+#include <conio.h>
+
+#include "cunit.h"
+#include "basic.h"
+#include "automated.h"
+
+#include "etch_global.h"
+#include "etchobj.h"
+
+
+int apr_setup(void);
+int apr_teardown(void);
+int this_setup();
+int this_teardown();
+apr_pool_t* g_apr_mempool;
+const char* pooltag = "etchpool";
+
+
+/* - - - - - - - - - - - - - -
+ * unit test infrastructure
+ * - - - - - - - - - - - - - -
+ */
+
+int init_suite(void)
+{
+ apr_setup();
+ etch_runtime_init(TRUE);
+ return this_setup();
+}
+
+int clean_suite(void)
+{
+ this_teardown();
+ etch_runtime_cleanup(0,0); /* free memtable and cache etc */
+ apr_teardown();
+ return 0;
+}
+
+int g_is_automated_test, g_bytes_allocated;
+
+#define IS_DEBUG_CONSOLE FALSE
+
+/*
+ * apr_setup()
+ * establish apache portable runtime environment
+ */
+int apr_setup(void)
+{
+ int result = apr_initialize();
+ if (result == 0)
+ { result = etch_apr_init();
+ g_apr_mempool = etch_apr_mempool;
+ }
+ if (g_apr_mempool)
+ apr_pool_tag(g_apr_mempool, pooltag);
+ else result = -1;
+ return result;
+}
+
+/*
+ * apr_teardown()
+ * free apache portable runtime environment
+ */
+int apr_teardown(void)
+{
+ if (g_apr_mempool)
+ apr_pool_destroy(g_apr_mempool);
+ g_apr_mempool = NULL;
+ apr_terminate();
+ return 0;
+}
+
+int this_setup()
+{
+ etch_apr_mempool = g_apr_mempool;
+ return 0;
+}
+
+int this_teardown()
+{
+ return 0;
+}
+#define THISTEST_OBJTYPE 0xeee0
+#define CLASSID_CLASS_A 0xeee1
+#define CLASSID_CLASS_B 0xeee2
+#define CLASSID_CLASS_C 0xeee3
+#define CLASSID_CLASS_X 0xeee4
+#define CLASSID_CLASS_Y 0xeee5
+#define CLASSID_CLASSA_VTABLE 0xeed1
+#define CLASSID_CLASSB_VTABLE 0xeed2
+#define CLASSID_CLASSC_VTABLE 0xeed3
+#define CLASSID_CLASSX_VTABLE 0xeed4
+#define CLASSID_CLASSY_VTABLE 0xeed5
+
+
+/**
+ * class_a: base class
+ */
+typedef struct class_a
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ vtabmask* vtab;
+ int (*destroy)(void*);
+ void*(*clone) (void*);
+ obj_gethashkey get_hashkey;
+ struct objmask* parent;
+ etchresult* result;
+ unsigned int refcount;
+ unsigned int length;
+ unsigned char is_null;
+ unsigned char is_copy;
+ unsigned char is_static;
+ unsigned char reserved;
+
+ etch_string* a_string;
+
+} class_a;
+
+
+/**
+ * class_a destructor
+ */
+int destroy_class_a(class_a* thisp)
+{
+ if (thisp->a_string)
+ thisp->a_string->destroy(thisp->a_string);
+
+ destroy_object((objmask*) thisp);
+ return 0;
+}
+
+/**
+ * class_a copy consttructor
+ */
+class_a* clone_class_a(class_a* origobj)
+{
+ class_a* newobj = (class_a*) new_object(sizeof(class_a), THISTEST_OBJTYPE, CLASSID_CLASS_A);
+ memcpy(newobj, origobj, origobj->length);
+ newobj->a_string = new_string(origobj->a_string->v.valw, ETCH_ENCODING_UTF16);
+ newobj->is_copy = TRUE;
+ return newobj;
+}
+
+
+/**
+ * class_a constructor
+ */
+class_a* new_class_a(const wchar_t* strval)
+{
+ vtabmask* vtab = NULL;
+ class_a* newobj = (class_a*) new_object(sizeof(class_a), THISTEST_OBJTYPE, CLASSID_CLASS_A);
+ newobj->destroy = destroy_class_a;
+ newobj->clone = clone_class_a;
+ newobj->a_string = new_string(strval, ETCH_ENCODING_UTF16);
+
+ if(!(vtab = cache_find(get_vtable_cachehkey(CLASSID_CLASSA_VTABLE), 0)))
+ { vtab = new_vtable(NULL, sizeof(vtabmask), CLASSID_CLASSA_VTABLE);
+ cache_insert(vtab->hashkey, vtab, FALSE);
+ }
+
+ newobj->vtab = vtab;
+ return newobj;
+}
+
+
+/**
+ * class_b: inherits from class_a
+ */
+typedef struct class_b
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ vtabmask* vtab;
+ int (*destroy)(void*);
+ void*(*clone) (void*);
+ obj_gethashkey get_hashkey;
+ class_a* parent;
+ etchresult* result;
+ unsigned int refcount;
+ unsigned int length;
+ unsigned char is_null;
+ unsigned char is_copy;
+ unsigned char is_static;
+ unsigned char reserved;
+
+ char* data;
+ int datasize;
+
+} class_b;
+
+
+/**
+ * class_b destructor
+ */
+int destroy_class_b(class_b* thisp)
+{
+ etch_free(thisp->data);
+ destroy_object((objmask*) thisp);
+ return 0;
+}
+
+
+/**
+ * class_b copy consttructor
+ */
+class_b* clone_class_b(class_b* origobj)
+{
+ class_b* newobj = (class_b*) new_object(sizeof(class_b), THISTEST_OBJTYPE, CLASSID_CLASS_B);
+ memcpy(newobj, origobj, origobj->length);
+
+ newobj->parent = origobj->parent?
+ origobj->parent->clone(origobj->parent):
+ new_class_a(NULL);
+
+ if (origobj->data)
+ { newobj->data = etch_malloc(origobj->datasize, ETCHTYPEB_BYTES);
+ newobj->datasize = origobj->datasize;
+ memcpy(newobj->data, origobj->data, origobj->datasize);
+ }
+
+ newobj->is_copy = TRUE;
+ return newobj;
+}
+
+
+/**
+ * class_b constructor
+ */
+class_b* new_class_b(class_a* parent, const int datalen)
+{
+ vtabmask* vtab = NULL;
+ etchparentinfo* inheritlist = NULL;
+ class_b* newobj = (class_b*) new_object(sizeof(class_b), THISTEST_OBJTYPE, CLASSID_CLASS_B);
+ newobj->parent = parent? parent: new_class_a(NULL);
+ newobj->destroy = destroy_class_b;
+ newobj->clone = clone_class_b;
+ newobj->data = etch_malloc(datalen, ETCHTYPEB_BYTES);
+ memset(newobj->data, 'x', datalen);
+ newobj->datasize = datalen;
+
+ if (NULL == (vtab = cache_find(get_vtable_cachehkey(CLASSID_CLASSB_VTABLE), 0)))
+ {
+ vtab = new_vtable(parent->vtab, sizeof(vtabmask), CLASSID_CLASSB_VTABLE);
+ cache_insert(vtab->hashkey, vtab, FALSE);
+
+ inheritlist = get_vtab_inheritance_list((objmask*)newobj,
+ 2, 1, CLASSID_CLASSB_VTABLE); /* create inheritance list */
+ inheritlist[1].obj_type = THISTEST_OBJTYPE;
+ inheritlist[1].class_id = CLASSID_CLASS_A;
+ }
+ newobj->vtab = vtab;
+ return newobj;
+}
+
+
+/**
+ * class_c: inherits from class_b
+ */
+typedef struct class_c
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ vtabmask* vtab;
+ int (*destroy)(void*);
+ void*(*clone) (void*);
+ obj_gethashkey get_hashkey;
+ class_b* parent;
+ etchresult* result;
+ unsigned int refcount;
+ unsigned int length;
+ unsigned char is_null;
+ unsigned char is_copy;
+ unsigned char is_static;
+ unsigned char reserved;
+
+ int* intarray;
+ int numitems;
+
+} class_c;
+
+
+/**
+ * class_c destructor
+ */
+int destroy_class_c(class_c* thisp)
+{
+ etch_free(thisp->intarray);
+ destroy_object((objmask*) thisp);
+ return 0;
+}
+
+
+/**
+ * class_c copy consttructor
+ */
+class_c* clone_class_c(class_c* origobj)
+{
+ class_c* newobj = (class_c*) new_object(sizeof(class_c), THISTEST_OBJTYPE, CLASSID_CLASS_C);
+ memcpy(newobj, origobj, sizeof(objmask));
+
+ if (origobj->parent)
+ newobj->parent = origobj->parent->clone(origobj->parent);
+ else newobj->parent = new_class_b(NULL, 0);
+
+ if (origobj->intarray)
+ {
+ newobj->intarray = etch_malloc(origobj->numitems * sizeof(int), ETCHTYPEB_BYTES);
+ newobj->numitems = origobj->numitems;
+ memcpy(newobj->intarray, origobj->intarray, origobj->numitems * sizeof(int));
+ }
+
+ newobj->is_copy = TRUE;
+ return newobj;
+}
+
+
+/**
+ * class_c constructor
+ */
+class_c* new_class_c(class_b* parent)
+{
+ int i = 0;
+ vtabmask* vtab = NULL;
+ etchparentinfo* inheritlist = NULL;
+ class_c* newobj = (class_c*) new_object(sizeof(class_c), THISTEST_OBJTYPE, CLASSID_CLASS_C);
+ newobj->parent = parent? parent: new_class_b(NULL, 0);
+ newobj->destroy = destroy_class_c;
+ newobj->clone = clone_class_c;
+
+ newobj->numitems = 4;
+ newobj->intarray = etch_malloc(4 * sizeof(int), ETCHTYPEB_BYTES);
+ for(; i < 4; i++) newobj->intarray[i] = i;
+
+ if (NULL == (vtab = cache_find(get_vtable_cachehkey(CLASSID_CLASSC_VTABLE), 0)))
+ {
+ vtab = new_vtable(parent->vtab, sizeof(vtabmask), CLASSID_CLASSC_VTABLE);
+ cache_insert(vtab->hashkey, vtab, FALSE);
+
+ inheritlist = get_vtab_inheritance_list((objmask*)newobj,
+ 3, 2, CLASSID_CLASSC_VTABLE); /* create inheritance list */
+ inheritlist[1].obj_type = THISTEST_OBJTYPE;
+ inheritlist[1].class_id = CLASSID_CLASS_B;
+ inheritlist[2].obj_type = THISTEST_OBJTYPE;
+ inheritlist[2].class_id = CLASSID_CLASS_A;
+ }
+ newobj->vtab = vtab;
+ return newobj;
+}
+
+
+/**
+ * class_y: inherits from class_x, but is flattened to contain class_x data.
+ * inheritance chain is identified through the object vtable inheritance list
+ */
+typedef struct class_y
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ vtabmask* vtab;
+ int (*destroy)(void*);
+ void*(*clone) (void*);
+ obj_gethashkey get_hashkey;
+ class_b* parent;
+ etchresult* result;
+ unsigned int refcount;
+ unsigned int length;
+ unsigned char is_null;
+ unsigned char is_copy;
+ unsigned char is_static;
+ unsigned char reserved;
+
+ int class_x_instance_data;
+ int class_y_instance_data;
+
+} class_y;
+
+
+/**
+ * class_x: parent of class_y
+ */
+typedef struct class_x
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ vtabmask* vtab;
+ int (*destroy)(void*);
+ void*(*clone) (void*);
+ obj_gethashkey get_hashkey;
+ class_b* parent;
+ etchresult* result;
+ unsigned int refcount;
+ unsigned int length;
+ unsigned char is_null;
+ unsigned char is_copy;
+ unsigned char is_static;
+ unsigned char reserved;
+
+ int class_x_instance_data;
+
+} class_x;
+
+
+/**
+ * class_x constructor
+ */
+class_x* new_class_x(int classx_data)
+{
+ class_x* newobj = (class_x*) new_object(sizeof(class_x), THISTEST_OBJTYPE, CLASSID_CLASS_X);
+
+ newobj->class_x_instance_data = classx_data;
+
+ /* class_x has no parent so we can omit vtable and inheritance list if we want */
+ return newobj;
+}
+
+
+/**
+ * class_y constructor
+ * inherits from class_x via inheritance type 2 - flat object
+ */
+class_y* new_class_y(int classx_data, int classy_data)
+{
+ etchparentinfo* inheritlist = NULL;
+ vtabmask* vtab = NULL;
+ class_y* newobj = (class_y*) new_object(sizeof(class_y), THISTEST_OBJTYPE, CLASSID_CLASS_Y);
+
+ newobj->class_x_instance_data = classx_data;
+ newobj->class_y_instance_data = classy_data;
+
+ if (NULL == (vtab = cache_find(get_vtable_cachehkey(CLASSID_CLASSY_VTABLE), 0)))
+ {
+ vtab = new_vtable(NULL, sizeof(vtabmask), CLASSID_CLASSY_VTABLE);
+ cache_insert(vtab->hashkey, vtab, FALSE);
+
+ inheritlist = get_vtab_inheritance_list((objmask*)newobj,
+ 2, 1, CLASSID_CLASSY_VTABLE); /* create inheritance list */
+ inheritlist[1].obj_type = THISTEST_OBJTYPE;
+ inheritlist[1].class_id = CLASSID_CLASS_X;
+ }
+ newobj->vtab = vtab;
+ return newobj;
+}
+
+
+void classarg_init_object(etch_objclass* arg)
+{
+ memset(arg, 0, sizeof(etch_objclass));
+ arg->obj_type = ETCHTYPEB_ETCHOBJECT;
+ arg->class_id = CLASSID_OBJECT;
+}
+
+
+/**
+ * classarg_init_nativearray()
+ * initialize class parameters for a wrapped primitive
+ */
+void classarg_init_primitive(etch_objclass* arg, short class_id)
+{
+ memset(arg, 0, sizeof(etch_objclass));
+ arg->obj_type = ETCHTYPEB_PRIMITIVE;
+ arg->class_id = class_id;
+}
+
+
+/**
+ * classarg_init_nativearray()
+ * initialize class parameters for native array
+ */
+void classarg_init_nativearray(etch_objclass* arg, short class_id, int dim, short conttype, short contclass )
+{
+ memset(arg, 0, sizeof(etch_objclass));
+ arg->obj_type = ETCHTYPEB_NATIVEARRAY;
+ arg->class_id = class_id;
+ arg->numdims = dim;
+ arg->content_obj_type = conttype;
+ arg->content_class_id = contclass;
+}
+
+
+/**
+ * classarg_init_customtype_scalar()
+ * initialize class parameters for a custom type with an inheritance hierarchy.
+ * real code would not allocate an inheritance list as we do here, this would
+ * be handled in the object vtable constructor, and the list subsequently
+ * accessed via the object's cached vtable.
+ */
+void classarg_init_customtype_scalar(etch_objclass* arg, short class_id, int numsupers,
+ short superclass_1, short superclass_2)
+{
+ memset(arg, 0, sizeof(etch_objclass));
+ arg->obj_type = THISTEST_OBJTYPE;
+ arg->class_id = class_id;
+
+ arg->inherits_from = etch_malloc(sizeof(etchparentinfo) * (numsupers + 1), ETCHTYPEB_BYTES);
+ arg->inherits_from[0].list_size = numsupers + 1;
+ arg->inherits_from[0].list_count = numsupers;
+
+ if (numsupers > 0)
+ { arg->inherits_from[1].obj_type = THISTEST_OBJTYPE;
+ arg->inherits_from[1].class_id = superclass_1;
+ }
+
+ if (numsupers > 1)
+ { arg->inherits_from[2].obj_type = THISTEST_OBJTYPE;
+ arg->inherits_from[2].class_id = superclass_2;
+ }
+}
+
+
+void classarg_cleanup(etch_objclass* target, etch_objclass* source)
+{
+ if (target->inherits_from) etch_free(target->inherits_from);
+ if (source->inherits_from) etch_free(source->inherits_from);
+ target->inherits_from = source->inherits_from = NULL;
+}
+
+
+/**
+ * test_is_assignable_1()
+ * test assignability of various classes
+ */
+void test_is_assignable_1(void)
+{
+ etch_objclass target, source;
+ int result = 0;
+
+ /* int32obj = int16obj */
+ classarg_init_primitive(&target, CLASSID_PRIMITIVE_INT32);
+ classarg_init_primitive(&source, CLASSID_PRIMITIVE_INT16);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, FALSE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ /* short[]obj = shortobj */
+ classarg_init_nativearray(&target, CLASSID_ARRAY_INT16, 1, ETCHTYPEB_PRIMITIVE, CLASSID_PRIMITIVE_INT16);
+ classarg_init_primitive(&source, CLASSID_PRIMITIVE_INT16);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, FALSE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ /* etchobj = longobj */
+ classarg_init_object(&target);
+ classarg_init_primitive(&source, CLASSID_PRIMITIVE_INT64);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, TRUE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ /* obj[]obj = shortobj */
+ classarg_init_nativearray(&target, CLASSID_ARRAY_OBJECT, 1, ETCHTYPEB_ETCHOBJECT, CLASSID_OBJECT);
+ classarg_init_primitive(&source, CLASSID_PRIMITIVE_INT16);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, FALSE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ /* obj[]obj = short[]obj */
+ classarg_init_nativearray(&target, CLASSID_ARRAY_OBJECT, 1, ETCHTYPEB_ETCHOBJECT, CLASSID_OBJECT);
+ classarg_init_nativearray(&source, CLASSID_ARRAY_INT16, 1, ETCHTYPEB_PRIMITIVE, CLASSID_PRIMITIVE_INT16);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, TRUE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ /* short[]obj = short[]obj */
+ classarg_init_nativearray(&target, CLASSID_ARRAY_INT16, 1, ETCHTYPEB_PRIMITIVE, CLASSID_PRIMITIVE_INT16);
+ classarg_init_nativearray(&source, CLASSID_ARRAY_INT16, 1, ETCHTYPEB_PRIMITIVE, CLASSID_PRIMITIVE_INT16);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, TRUE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ /* custom1obj = custom0obj */
+ classarg_init_customtype_scalar(&target, CLASSID_CLASS_A, 0, 0, 0);
+ classarg_init_customtype_scalar(&source, CLASSID_CLASS_B, 1, CLASSID_CLASS_A, 0);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, TRUE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+ classarg_cleanup(&source, &target);
+
+ /* custom2obj = custom0obj */
+ classarg_init_customtype_scalar(&target, CLASSID_CLASS_A, 0, 0, 0);
+ classarg_init_customtype_scalar(&source, CLASSID_CLASS_C, 2, CLASSID_CLASS_B, CLASSID_CLASS_A);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, TRUE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+ classarg_cleanup(&source, &target);
+
+ /* custom2obj = custom1obj */
+ classarg_init_customtype_scalar(&target, CLASSID_CLASS_B, 1, CLASSID_CLASS_A, 0);
+ classarg_init_customtype_scalar(&source, CLASSID_CLASS_C, 2, CLASSID_CLASS_B, CLASSID_CLASS_A);
+ result = etchobj_is_assignable_from(&target, &source);
+ CU_ASSERT_EQUAL(result, TRUE);
+ result = etchobj_is_assignable_from(&source, &target);
+ CU_ASSERT_EQUAL(result, FALSE);
+ classarg_cleanup(&source, &target);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_assign_long_to_object
+ */
+void test_assign_long_to_object(void)
+{
+ char* objval = etch_malloc(128, ETCHTYPEB_BYTES);
+ etch_object* class_object = new_etch_object(CLASSID_OBJECT, objval);
+ etch_int64* class_long = new_int64(0);
+ objmask* resultobj = NULL;
+ int result = etchobj_is_assignable_fromobj((objmask*) class_object, (objmask*) class_long);
+ CU_ASSERT_EQUAL_FATAL(result, TRUE);
+
+ /* an assignment to object causes the source object to be
+ * wrapped by the target object */
+
+ resultobj = etchobj_assign_to((objmask*) class_object, (objmask*) class_long);
+ CU_ASSERT_PTR_EQUAL(resultobj, class_object);
+
+ class_long->destroy(class_long);
+ class_object->destroy(class_object);
+
+ /* we destroy class_long allocated above, since the assignment caused
+ * it to be wrapped by, but of course not consumed by, class_object.
+ * that is, class_object now contains a reference to class_long, but
+ * does not own the reference (destructor will not attempt to free it).
+ * we do not destroy the character vector objval allocated above, since
+ * the assignment to class_object caused any content already owned by it,
+ * in this case objval, to be destroyed as part of the assignment.
+ */
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_invalid_array_assignment_1
+ * ensure assignment fails when dimensions do not match
+ */
+void test_invalid_array_assignment_1(void)
+{
+ const int numdimbyte = 1, dim0byte = 4;
+ const int numdimobj = 2, dim0obj = 4, dim1obj = 2;
+ objmask* resultobj = NULL;
+
+ etch_nativearray* array_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimbyte, dim0byte, 0, 0);
+
+ etch_nativearray* array_of_object = new_nativearray
+ (CLASSID_ARRAY_OBJECT, sizeof(void*), numdimobj, dim0obj, dim1obj, 0);
+
+ int result = etchobj_is_assignable_fromobj((objmask*) array_of_object, (objmask*) array_of_byte);
+ CU_ASSERT_EQUAL_FATAL(result, FALSE);
+
+ resultobj = etchobj_assign_to((objmask*) array_of_object, (objmask*) array_of_byte);
+ CU_ASSERT_PTR_EQUAL(resultobj, NULL);
+
+ array_of_byte->destroy(array_of_byte);
+ array_of_object->destroy(array_of_object);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_invalid_array_assignment_2
+ * ensure assignment fails when types do not match
+ */
+void test_invalid_array_assignment_2(void)
+{
+ const int numdim = 1, dim0 = 4;
+ objmask* resultobj = NULL;
+
+ etch_nativearray* array_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdim, dim0, 0, 0);
+
+ etch_nativearray* array_of_bool = new_nativearray
+ (CLASSID_ARRAY_BOOL, sizeof(byte), numdim, dim0, 0, 0);
+
+ int result = etchobj_is_assignable_fromobj((objmask*) array_of_bool, (objmask*) array_of_byte);
+ CU_ASSERT_EQUAL(result, FALSE);
+ result = etchobj_is_assignable_fromobj((objmask*) array_of_byte, (objmask*) array_of_bool);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ resultobj = etchobj_assign_to((objmask*) array_of_bool, (objmask*) array_of_byte);
+ CU_ASSERT_EQUAL(result, NULL);
+
+ array_of_byte->destroy(array_of_byte);
+ array_of_bool->destroy(array_of_bool);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_assign_arrayofbyte_to_arrayofobject
+ */
+void test_assign_arrayofbyte_to_arrayofobject(void)
+{
+ const int numdimensions = 2, dim0count = 4, dim1count = 2;
+ objmask* resultobj = NULL;
+
+ etch_nativearray* array_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ etch_nativearray* array_of_object = new_nativearray
+ (CLASSID_ARRAY_OBJECT, sizeof(void*), numdimensions, dim0count, dim1count, 0);
+
+ /* an assignment of one array to the other replaces all array attributes
+ * and content in the target object. the target object will not own the
+ * array content of course */
+
+ int result = etchobj_is_assignable_fromobj((objmask*) array_of_object, (objmask*) array_of_byte);
+ CU_ASSERT_EQUAL_FATAL(result, TRUE);
+
+ resultobj = etchobj_assign_to((objmask*) array_of_object, (objmask*) array_of_byte);
+ CU_ASSERT_PTR_EQUAL(resultobj, array_of_object);
+
+ array_of_byte->destroy(array_of_byte);
+ array_of_object->destroy(array_of_object);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_assign_verify_arraybyte_to_arrayobj
+ * assign array of byte to array of object and verify content is identical
+ */
+void test_assign_verify_arraybyte_to_arrayobj(void)
+{
+ int i = 0, j = 0, result = 0;
+ char x[2][4] = { {'a','b','c','d'}, {'e','f','g','h'}, }, thisx = 0;
+ const int numdimensions = 2, dim0count = 4, dim1count = 2;
+ objmask* resultobj = NULL;
+
+ etch_nativearray* array_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ etch_nativearray* array_of_object = new_nativearray
+ (CLASSID_ARRAY_OBJECT, sizeof(void*), numdimensions, dim0count, dim1count, 0);
+
+ for(i = 0; i < dim1count; i++) /* initialize array of byte */
+ {
+ for(j = 0; j < dim0count; j++)
+ {
+ result = array_of_byte->put2(array_of_byte, &x[i][j], i, j);
+ CU_ASSERT_EQUAL(result, 0);
+ }
+ }
+
+ resultobj = etchobj_assign_to((objmask*) array_of_object, (objmask*) array_of_byte);
+ CU_ASSERT_PTR_EQUAL_FATAL(resultobj, array_of_object);
+
+ for(i = 0; i < dim1count; i++) /* verify arrays are now the same */
+ {
+ for(j = 0; j < dim0count; j++)
+ {
+ result = array_of_object->get2(array_of_object, &thisx, i, j);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(x[i][j], thisx);
+ }
+ }
+
+ array_of_byte->destroy(array_of_byte);
+ array_of_object->destroy(array_of_object);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_assign_arrayofbyte_to_arrayofbyte
+ */
+void test_assign_arrayofbyte_to_arrayofbyte(void)
+{
+ const int numdimensions = 2, dim0count = 4, dim1count = 2;
+ objmask* resultobj = NULL;
+
+ etch_nativearray* array1_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ etch_nativearray* array2_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ int result = etchobj_is_assignable_fromobj((objmask*) array1_of_byte, (objmask*) array2_of_byte);
+ CU_ASSERT_EQUAL_FATAL(result, TRUE);
+ result = etchobj_is_assignable_fromobj((objmask*) array2_of_byte, (objmask*) array1_of_byte);
+ CU_ASSERT_EQUAL_FATAL(result, TRUE);
+
+ resultobj = etchobj_assign_to((objmask*) array1_of_byte, (objmask*) array2_of_byte);
+ CU_ASSERT_PTR_EQUAL(resultobj, array1_of_byte);
+
+ resultobj = etchobj_assign_to((objmask*) array2_of_byte, (objmask*) array1_of_byte);
+ CU_ASSERT_PTR_EQUAL(resultobj, array2_of_byte);
+
+ array1_of_byte->destroy(array1_of_byte);
+ array2_of_byte->destroy(array2_of_byte);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_assign_verify_arraybyte_to_arraybyte
+ * assign array of byte to array of byte and verify content is identical
+ */
+void test_assign_verify_arraybyte_to_arraybyte(void)
+{
+ int i = 0, j = 0, result = 0;
+ char x[2][4] = { {'a','b','c','d'}, {'e','f','g','h'}, }, thisx = 0;
+ char y[2][4] = { {'s','t','u','v'}, {'w','x','y','z'}, };
+ const int numdimensions = 2, dim0count = 4, dim1count = 2;
+ objmask* resultobj = NULL;
+
+ etch_nativearray* array1_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ etch_nativearray* array2_of_byte = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ for(i = 0; i < dim1count; i++) /* initialize both arrays */
+ {
+ for(j = 0; j < dim0count; j++)
+ {
+ result = array1_of_byte->put2(array1_of_byte, &x[i][j], i, j);
+ CU_ASSERT_EQUAL(result, 0);
+
+ result = array2_of_byte->put2(array2_of_byte, &y[i][j], i, j);
+ CU_ASSERT_EQUAL(result, 0);
+ }
+ }
+
+ resultobj = etchobj_assign_to((objmask*) array1_of_byte, (objmask*) array2_of_byte);
+ CU_ASSERT_PTR_EQUAL_FATAL(resultobj, array1_of_byte);
+
+ for(i = 0; i < dim1count; i++) /* verify assignment */
+ {
+ for(j = 0; j < dim0count; j++)
+ {
+ result = array1_of_byte->get2(array1_of_byte, &thisx, i, j);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(y[i][j], thisx);
+ }
+ }
+
+ array1_of_byte->destroy(array1_of_byte);
+ array2_of_byte->destroy(array2_of_byte);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_assign_derived_2
+ * test that inheritance type 2-derived object can be assigned to its parent
+ */
+void test_assign_derived_2(void)
+{
+ class_a* class_parent = NULL;
+ class_b* class_child = NULL;
+ objmask* resultobj = NULL;
+ int result = 0;
+
+ class_parent = new_class_a(L"it works!");
+ class_child = new_class_b(class_parent, 128);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_child->parent);
+ CU_ASSERT_PTR_NULL(class_parent->parent);
+
+ result = etchobj_is_assignable_fromobj((objmask*) class_child, (objmask*) class_parent);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ result = etchobj_is_assignable_fromobj((objmask*) class_parent, (objmask*) class_child);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ /* these objects use type 2 inheritance, in which inherited objects chain to
+ * instantiated parent objects. for such objects, when we assign child class
+ * to parent class, the result of the assignment couldl be a different memory
+ * reference than the requested target. however in this case, the object we
+ * are assigning to is in fact the same object as is in the source object's
+ * inheritance chain (since we passed it to the object's constructor).
+ * is not known at this writing whether this scenario can exist in etch c;
+ * that is, if we will ever use this inheritance model in conjunction with
+ * the assignment of child to parent.
+ */
+ resultobj = etchobj_assign_to((objmask*) class_parent, (objmask*) class_child);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(resultobj);
+ CU_ASSERT_EQUAL(resultobj->class_id, class_parent->class_id);
+
+ /* an object destructor will recursively destroy() its superclass instances */
+ class_child->destroy(class_child);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_assign_derived_1a
+ * test that inheritance type 2-derived object can be assigned to its parent
+ */
+void test_assign_derived_2a(void)
+{
+ class_a* class_parent = NULL;
+ class_b* class_child1 = NULL;
+ class_c* class_child2 = NULL;
+ objmask* resultobj = NULL;
+ int result = 0;
+
+ class_parent = new_class_a(L"it works!");
+ class_child1 = new_class_b(class_parent, 128);
+ class_child2 = new_class_c(class_child1);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_child2->parent);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_child1->parent);
+ CU_ASSERT_PTR_NULL(class_parent->parent);
+
+ result = etchobj_is_assignable_fromobj((objmask*) class_child2, (objmask*) class_parent);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ result = etchobj_is_assignable_fromobj((objmask*) class_parent, (objmask*) class_child2);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ /* see comments at test_assign_derived_2() - they apply again here */
+ resultobj = etchobj_assign_to((objmask*) class_parent, (objmask*) class_child2);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(resultobj);
+ CU_ASSERT_EQUAL(resultobj->class_id, class_parent->class_id);
+
+ /* an object destructor will recursively destroy() its superclass instances */
+ class_child2->destroy(class_child2);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_assign_derived_1
+ * test that inheritance type 1-derived object can be assigned to its parent
+ */
+void test_assign_derived_1(void)
+{
+ class_x* class_parent = NULL;
+ class_y* class_child = NULL;
+ objmask* resultobj = NULL;
+ const int PARENT_CLASSX_DATA = 1, CHILD_CLASSX_DATA = 1000, CHILD_CLASSY_DATA = 1001;
+ int result = 0;
+
+ class_parent = new_class_x(PARENT_CLASSX_DATA);
+ class_child = new_class_y(CHILD_CLASSX_DATA, CHILD_CLASSY_DATA);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_parent);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_child);
+
+ result = etchobj_is_assignable_fromobj((objmask*) class_child, (objmask*) class_parent);
+ CU_ASSERT_EQUAL(result, FALSE);
+
+ result = etchobj_is_assignable_fromobj((objmask*) class_parent, (objmask*) class_child);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ /* these objects use type 1 inheritance, in which inherited objects contain
+ * their parent's instance data;. there is no physical chaining of objects.
+ * rather inheritance is identified from the object vtable's inheritance list.
+ */
+ resultobj = etchobj_assign_to((objmask*) class_parent, (objmask*) class_child);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(resultobj);
+ CU_ASSERT_EQUAL(resultobj->class_id, class_parent->class_id);
+ /* verify that parent's instance data was replaced with that of the child */
+ CU_ASSERT_EQUAL(((class_x*)resultobj)->class_x_instance_data, class_child->class_x_instance_data);
+
+ class_child->destroy(class_child);
+ class_parent->destroy(class_parent);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * main
+ */
+int _tmain(int argc, _TCHAR* argv[])
+{
+ char c=0;
+ CU_pSuite ps = 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_etchobject");
+ ps = CU_add_suite("etchobject test suite", init_suite, clean_suite);
+ etch_watch_id = 0;
+
+ CU_add_test(ps, "test assignability", test_is_assignable_1);
+ CU_add_test(ps, "assign long to object", test_assign_long_to_object);
+ CU_add_test(ps, "attempt invalid array assignment 1", test_invalid_array_assignment_1);
+ CU_add_test(ps, "attempt invalid array assignment 2", test_invalid_array_assignment_2);
+ CU_add_test(ps, "assign byte[][] to object[][]", test_assign_arrayofbyte_to_arrayofobject);
+ CU_add_test(ps, "assign byte[][] to object[][] and verify", test_assign_verify_arraybyte_to_arrayobj);
+ CU_add_test(ps, "assign byte[][] to byte[][]", test_assign_arrayofbyte_to_arrayofbyte);
+ CU_add_test(ps, "assign byte[][] to byte[][] and verify", test_assign_verify_arraybyte_to_arraybyte);
+ CU_add_test(ps, "assign child to parent (type 2)", test_assign_derived_2);
+ CU_add_test(ps, "assign 2x child to parent (type 2)", test_assign_derived_2a);
+ CU_add_test(ps, "assign child to parent (type 1)", test_assign_derived_1);
+
+ 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();
+}
+
Added: incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_cache.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_cache.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_cache.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_cache.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,314 @@
+/* $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * test_cache.c
+ * test the runtime object cache
+ * we can swap out cache back ends and this test should work the same regardless
+ */
+#include "apr_time.h" /* some apr must be included first */
+#include "etchthread.h"
+#include <tchar.h>
+#include <stdio.h>
+#include <conio.h>
+
+#include "cunit.h"
+#include "basic.h"
+#include "automated.h"
+
+#include "etch_global.h"
+#include "etch_arraylist.h"
+
+int apr_setup(void);
+int apr_teardown(void);
+int this_setup();
+int this_teardown();
+apr_pool_t* g_apr_mempool;
+const char* pooltag = "etchpool";
+
+
+/* - - - - - - - - - - - - - -
+ * unit test infrastructure
+ * - - - - - - - - - - - - - -
+ */
+
+int init_suite(void)
+{
+ apr_setup();
+ etch_runtime_init(TRUE);
+ return this_setup();
+}
+
+int clean_suite(void)
+{
+ this_teardown();
+ etch_runtime_cleanup(0,0); /* free memtable and cache etc */
+ apr_teardown();
+ return 0;
+}
+
+int g_is_automated_test, g_bytes_allocated;
+
+#define IS_DEBUG_CONSOLE FALSE
+
+/*
+ * apr_setup()
+ * establish apache portable runtime environment
+ */
+int apr_setup(void)
+{
+ int result = apr_initialize();
+ if (result == 0)
+ { result = etch_apr_init();
+ g_apr_mempool = etch_apr_mempool;
+ }
+ if (g_apr_mempool)
+ apr_pool_tag(g_apr_mempool, pooltag);
+ else result = -1;
+ return result;
+}
+
+/*
+ * apr_teardown()
+ * free apache portable runtime environment
+ */
+int apr_teardown(void)
+{
+ if (g_apr_mempool)
+ apr_pool_destroy(g_apr_mempool);
+ g_apr_mempool = NULL;
+ apr_terminate();
+ return 0;
+}
+
+int this_setup()
+{
+ etch_apr_mempool = g_apr_mempool;
+ return 0;
+}
+
+int this_teardown()
+{
+ return 0;
+}
+
+
+/**
+ * This subtest instantiates various etch objects which cache some part of
+ * themselves, and destroys the objects. At each step the test verifies that
+ * the cache contains the expected number of entries, e.g. if I create
+ * multiple hashtables I should only have cached one hashtable vtable.
+ */
+void test_multiple_items(void)
+{
+ int cache_start_count = 0, cache_current_count;
+ int result1 = 0, result2 = 0, result3 = 0;
+ etch_hashtable* myhashtab1 = NULL;
+ etch_hashtable* myhashtab2 = NULL;
+ etch_hashtable* myhashtab3 = NULL;
+ etch_hashitem hashbucket;
+ etch_hashitem* myentry = &hashbucket;
+
+ wchar_t* wstr1 = L"abracadabra";
+ wchar_t* wstr2 = L"gilgamesh";
+ wchar_t* wstr3 = L"antidisestablishmentarianism";
+
+ const size_t numElements1 = wcslen(wstr1);
+ const size_t numElements2 = wcslen(wstr2);
+ const size_t numElements3 = wcslen(wstr3);
+
+ const size_t numBytes1 = sizeof(wchar_t) * numElements1;
+ const size_t numBytes2 = sizeof(wchar_t) * numElements2;
+ const size_t numBytes3 = sizeof(wchar_t) * numElements3;
+
+ size_t actlen1 = 0, actlen2 = 0, actlen3 = 0;
+ wchar_t *key1 = NULL, *key2 = NULL, *key3 = NULL;
+
+ key1 = malloc(numBytes1 + 2);
+ key2 = malloc(numBytes2 + 2);
+ key3 = malloc(numBytes3 + 2);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(key1);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(key2);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(key3);
+
+ /* create one hashtable first, so in case we are tracking memory, we ensure that
+ * the hashtable code module paths will already be cached. */
+ myhashtab1 = new_hashtable(16);
+
+ cache_start_count = cache_count();
+
+ result1 = wcscpy_s(key1, numElements1+1, wstr1); /* wcscpy_s param 2 must be */
+ result2 = wcscpy_s(key2, numElements2+1, wstr2); /* number of characters + 1 */
+ result3 = wcscpy_s(key3, numElements3+1, wstr3);
+ actlen1 = wcslen(key1); actlen2 = wcslen(key2); actlen3 = wcslen(key3);
+
+ myhashtab2 = new_hashtable(16);
+ myhashtab3 = new_hashtable(16);
+
+ /* we should not have cached any more hashtable vtables */
+ cache_current_count = cache_count();
+ CU_ASSERT_EQUAL(cache_current_count,cache_start_count);
+
+ myhashtab1->vtab->insert(myhashtab1->realtable, key1, (int)numBytes1, NULL,0,0,0);
+ myhashtab2->vtab->insert(myhashtab2->realtable, key2, (int)numBytes2, NULL,0,0,0);
+ myhashtab2->vtab->insert(myhashtab3->realtable, key3, (int)numBytes3, NULL,0,0,0);
+
+ /* TODO instantiate some other object here which uses the cache */
+
+ destroy_hashtable(myhashtab1, TRUE, TRUE);
+ destroy_hashtable(myhashtab2, TRUE, TRUE);
+ destroy_hashtable(myhashtab3, TRUE, TRUE);
+ /* note that key1 and key2 are now dangling pointers since we asked the
+ * hashtable to free keys and values memory
+ */
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_intkeys()
+ * tests caching using integer keys as we might do for etchobjects such as vtables
+ */
+void test_intkeys(void)
+{
+ int i, startsize, size;
+ const int STARTKEY = 0, ENDKEY = 512, KEYCOUNT = ENDKEY - STARTKEY;
+ char* teststring = "it works!";
+ char* item = etch_malloc(sizeof(teststring),0);
+ memcpy(item, teststring, sizeof(teststring));
+
+ startsize = cache_count();
+
+ for(i = STARTKEY; i < ENDKEY; i++)
+ cache_add(i, item);
+
+ size = cache_count();
+ CU_ASSERT_EQUAL(size, KEYCOUNT + startsize);
+
+ for(i = STARTKEY; i < ENDKEY; i++)
+ CU_ASSERT_PTR_NOT_NULL(cache_find(i, 0));
+
+ for(i = STARTKEY; i < ENDKEY; i++)
+ CU_ASSERT_PTR_NOT_NULL(cache_del(i));
+
+ size = cache_count();
+ CU_ASSERT_EQUAL(size, startsize);
+
+ etch_free(item);
+
+ g_bytes_allocated = etch_showmem(0,0); /* verify all memory freed */
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_intkeys()
+ * tests caching using string keys with no values, as we might do for source
+ * file paths in the debug allocator
+ */
+void test_pathkeys(void)
+{
+ char* path1 = "..\\..\\foo\\bar\\file1.dat";
+ char* path2 = "..\\..\\foo\\bar\\file2.dat";
+ char* path3 = "c:\\the\\quick\\brown\\fox\\jumped\\over\\the\\lazy\\dog\\file3.dat";
+ unsigned hash1 = 0, hash2 = 0, hash3 = 0;
+ char* namefound = NULL;
+ etch_hashitem hashbucket;
+ etch_hashitem* thisitem = &hashbucket;
+ int result = 0;
+ int len1 = (int)strlen(path1), len2 = (int)strlen(path2), len3 = (int)strlen(path3);
+
+ hash1 = cache_insertx (path1, NULL, FALSE);
+ hash2 = cache_insertx (path2, NULL, FALSE);
+ hash3 = cache_insertx (path3, NULL, FALSE);
+
+ memset(thisitem, 0, sizeof(etch_hashitem));
+ cache_findx(path1, &thisitem);
+ CU_ASSERT_PTR_NOT_NULL(thisitem->key);
+ CU_ASSERT_EQUAL(hash1, thisitem->hash);
+ result = strncmp(path1, thisitem->key, len1);
+ CU_ASSERT_EQUAL(result,0);
+
+ memset(thisitem, 0, sizeof(etch_hashitem));
+ cache_findx(path2, &thisitem);
+ CU_ASSERT_PTR_NOT_NULL(thisitem->key);
+ CU_ASSERT_EQUAL(hash2, thisitem->hash);
+ result = strncmp(path2, thisitem->key, len2);
+ CU_ASSERT_EQUAL(result,0);
+
+ memset(thisitem, 0, sizeof(etch_hashitem));
+ cache_findx(path3, &thisitem);
+ CU_ASSERT_PTR_NOT_NULL(thisitem->key);
+ CU_ASSERT_EQUAL(hash3, thisitem->hash);
+ result = strncmp(path3, thisitem->key, len3);
+ CU_ASSERT_EQUAL(result,0);
+
+ memset(thisitem, 0, sizeof(etch_hashitem));
+ cache_find_by_hash(hash1, &thisitem);
+ CU_ASSERT_PTR_NOT_NULL(thisitem->key);
+ result = strncmp(path1, thisitem->key, len1);
+ CU_ASSERT_EQUAL(result,0);
+
+ memset(thisitem, 0, sizeof(etch_hashitem));
+ cache_find_by_hash(hash2, &thisitem);
+ CU_ASSERT_PTR_NOT_NULL(thisitem->key);
+ result = strncmp(path2, thisitem->key, len2);
+ CU_ASSERT_EQUAL(result,0);
+
+ memset(thisitem, 0, sizeof(etch_hashitem));
+ cache_find_by_hash(hash3, &thisitem);
+ CU_ASSERT_PTR_NOT_NULL(thisitem->key);
+ result = strncmp(path3, thisitem->key, len3);
+ CU_ASSERT_EQUAL(result,0);
+}
+
+
+/**
+ * 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 CU_get_error();
+ CU_set_output_filename("../test_cache");
+ pSuite = CU_add_suite("suite_cache", init_suite, clean_suite);
+
+ CU_add_test(pSuite, "test path strings as keys", test_pathkeys);
+ CU_add_test(pSuite, "multiple of same object test", test_multiple_items);
+ CU_add_test(pSuite, "integer cache key test", test_intkeys);
+
+ 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();
+}
+
Added: incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_conn.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_conn.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_conn.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_conn.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,184 @@
+/**
+ * etchconn test routines.
+ */
+
+ #include "CUnit.h"
+#include "Basic.h"
+#include "Console.h"
+#include "Automated.h"
+#include "etchconn.h"
+#include "apr_time.h"
+#include "etchlog.h"
+
+#define MAX_TEST_CONNECTIONS 10
+
+static apr_pool_t *pool_ptr = NULL;
+static etch_tcpconn *tcpconn_ptr = NULL;
+static etch_tcpconn *tcpconn2_ptr = NULL;
+static etch_tcplistener *listener_ptr = NULL;
+static etch_tcpconn *accepted[MAX_TEST_CONNECTIONS];
+static BOOLEAN got_accepted(apr_socket_t *socket_ptr);
+
+static void got_data(void *data_ptr, size_t len);
+
+int setup(void)
+{
+ apr_status_t r;
+ r = apr_initialize();
+ if (r == APR_SUCCESS)
+ r = apr_pool_create(&pool_ptr, NULL);
+
+ if (r == APR_SUCCESS )
+ {
+ listener_ptr = etchconn_create_listener("127.0.0.1", 7302, 5, 5, pool_ptr);
+ if (listener_ptr != NULL)
+ listener_ptr->conn.handle_accepted = got_accepted;
+ tcpconn_ptr = etchconn_create_tcp("127.0.0.1", 7302, 5, pool_ptr);
+ /* create another connection to listener */
+ tcpconn2_ptr = etchconn_create_tcp("127.0.0.1", 7302, 5, pool_ptr);
+ }
+
+ memset(accepted, 0, sizeof(accepted));
+
+ return (listener_ptr != NULL && tcpconn_ptr != NULL && tcpconn2_ptr != NULL ? 0 : 1);
+}
+
+int teardown(void)
+{
+ int i;
+ etchconn_destroy((etchconn*)tcpconn_ptr);
+ etchconn_destroy((etchconn*)tcpconn2_ptr);
+ etchconn_destroy((etchconn*)listener_ptr);
+
+ for(i = 0; i < MAX_TEST_CONNECTIONS && accepted[i] != NULL; i++)
+ {
+ etchconn_destroy((etchconn*)accepted[i]);
+ accepted[i] = NULL;
+ }
+
+ if (pool_ptr != NULL)
+ apr_pool_destroy(pool_ptr);
+ pool_ptr = NULL;
+
+ apr_terminate();
+
+ return 0;
+}
+
+static BOOLEAN got_accepted(apr_socket_t *socket_ptr)
+{
+ BOOLEAN rc = FALSE;
+ int i;
+
+ etch_tcpconn *accepted_ptr = etchconn_create_tcp_with_socket(socket_ptr);
+ if (accepted_ptr != NULL)
+ {
+ /* need to initialize data handler */
+ accepted_ptr->conn.handle_data = got_data;
+ rc = etchconn_start((etchconn *) accepted_ptr);
+
+ /* save the pointer for later releasing */
+ i = 0;
+
+ while (i < MAX_TEST_CONNECTIONS && accepted[i] != NULL)
+ ++i;
+ if (i < MAX_TEST_CONNECTIONS)
+ accepted[i] = accepted_ptr;
+ }
+
+ return rc;
+}
+
+static void got_data(void *data_ptr, size_t len)
+{
+ etchlog_report("etchconntest", ETCHLOG_DEBUG, "Got data: %s\n", (const char*) data_ptr);
+}
+
+void testSimple(void)
+{
+ int i;
+ int rc;
+ char data[] = "this is testSimple data.";
+
+ CU_ASSERT(etchconn_start((etchconn*)listener_ptr));
+ rc = etchmon_wait_until_equal(listener_ptr->conn.monitor_ptr, ETCHCONN_UP, (strlen(ETCHCONN_UP)+1)*sizeof(char),0);
+ CU_ASSERT(etchconn_start((etchconn*)tcpconn_ptr));
+
+ rc = etchmon_wait_until_equal(tcpconn_ptr->conn.monitor_ptr, ETCHCONN_UP, (strlen(ETCHCONN_UP)+1)*sizeof(char),0);
+ CU_ASSERT(rc==ETCHMON_STATUS_SUCCESS);
+ for(i = 0; i < 50; i++)
+ {
+ CU_ASSERT(etchconn_send_tcp((etchconn*)tcpconn_ptr, data, (strlen(data)+1)*sizeof(char)));
+ apr_sleep(100000);
+ }
+ apr_sleep(1000000);
+ etchconn_stop((etchconn*)tcpconn_ptr);
+
+ apr_sleep(1000000);
+ CU_ASSERT_PTR_NOT_NULL(accepted[0]);
+ etchconn_stop((etchconn*)accepted[0]);
+
+ etchconn_stop((etchconn*)listener_ptr);
+}
+
+void testMoreConnections(void)
+{
+ int i;
+ int rc;
+ char data[] = "CONN1: this is testMoreConnections data.";
+ char data2[] = "CONN2: this is testMoreConnections data.";
+
+ CU_ASSERT(etchconn_start((etchconn*)listener_ptr));
+ rc = etchmon_wait_until_equal(listener_ptr->conn.monitor_ptr, ETCHCONN_UP, (strlen(ETCHCONN_UP)+1)*sizeof(char),0);
+ CU_ASSERT(etchconn_start((etchconn*)tcpconn_ptr));
+
+ /* create another connection to listener */
+ CU_ASSERT(etchconn_start((etchconn*) tcpconn2_ptr));
+
+ rc = etchmon_wait_until_equal(tcpconn_ptr->conn.monitor_ptr, ETCHCONN_UP, (strlen(ETCHCONN_UP)+1)*sizeof(char),0);
+ CU_ASSERT(rc==ETCHMON_STATUS_SUCCESS);
+
+ rc = etchmon_wait_until_equal(tcpconn2_ptr->conn.monitor_ptr, ETCHCONN_UP, (strlen(ETCHCONN_UP)+1)*sizeof(char),0);
+ CU_ASSERT(rc==ETCHMON_STATUS_SUCCESS);
+
+ for(i = 0; i < 100; i++)
+ {
+ CU_ASSERT(etchconn_send_tcp((etchconn*)tcpconn_ptr, data, (strlen(data)+1)*sizeof(char)));
+ CU_ASSERT(etchconn_send_tcp((etchconn*)tcpconn2_ptr, data2, (strlen(data2)+1)*sizeof(char)));
+ apr_sleep(10000);
+ }
+
+ apr_sleep(1000000);
+ etchconn_stop((etchconn*)tcpconn_ptr);
+
+ etchconn_stop((etchconn*)tcpconn2_ptr);
+
+ apr_sleep(1000000);
+ CU_ASSERT_PTR_NOT_NULL(accepted[0]);
+ etchconn_stop((etchconn*)accepted[0]);
+
+ CU_ASSERT_PTR_NOT_NULL(accepted[1]);
+ etchconn_stop((etchconn*)accepted[1]);
+
+ etchconn_stop((etchconn*)listener_ptr);
+}
+
+
+int main(int argc, char **argv)
+{
+ CU_pSuite ps;
+ CU_pTest pt;
+
+ printf("hellor world!");
+ CU_initialize_registry();
+
+ ps = CU_add_suite("etchconn test suit", setup, teardown);
+ pt = CU_add_test(ps, "testSimple", testSimple);
+ pt = CU_add_test(ps, "testMoreConnections", testMoreConnections);
+
+ CU_automated_run_tests();
+ /*CU_console_run_tests();*/
+
+ CU_cleanup_registry();
+ return 0;
+}
\ No newline at end of file