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 [23/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_etchobject.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_etchobject.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_etchobject.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_etchobject.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,1089 @@
+/* $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_etchobject.c.c -- test etch object inheritance and primitives
+ */
+#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;
+}
+
+/**
+ * class_a: base class
+ */
+typedef struct class_a
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ struct objmask* 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), 413, 0);
+ memcpy(newobj, origobj, sizeof(objmask));
+ newobj->a_string = new_string(origobj->a_string->v.valw, ETCH_ENCODING_UTF16);
+ return newobj;
+}
+
+
+/**
+ * class_a constructor
+ */
+class_a* new_class_a(const wchar_t* strval)
+{
+ class_a* newobj = (class_a*) new_object(sizeof(class_a), 403, 0);
+ newobj->destroy = destroy_class_a;
+ newobj->clone = clone_class_a;
+ newobj->a_string = new_string(strval, ETCH_ENCODING_UTF16);
+ return newobj;
+}
+
+
+/**
+ * class_b: inherits from class_a
+ */
+typedef struct class_b
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ struct objmask* 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), 415, 0);
+ memcpy(newobj, origobj, sizeof(objmask));
+
+ newobj->parent = origobj->parent?
+ origobj->parent->clone(origobj->parent):
+ new_class_a(NULL);
+
+ if (origobj->data)
+ {
+ newobj->data = etch_malloc(origobj->datasize, 412);
+ newobj->datasize = origobj->datasize;
+ memcpy(newobj->data, origobj->data, origobj->datasize);
+ }
+
+ return newobj;
+}
+
+
+/**
+ * class_b constructor
+ */
+class_b* new_class_b(class_a* parent, const int datalen)
+{
+ class_b* newobj = (class_b*) new_object(sizeof(class_b), 404, 0);
+ newobj->parent = parent? parent: new_class_a(NULL);
+ newobj->destroy = destroy_class_b;
+ newobj->clone = clone_class_b;
+ newobj->data = etch_malloc(datalen, 402);
+ memset(newobj->data, 'x', datalen);
+ newobj->datasize = datalen;
+ return newobj;
+}
+
+
+/**
+ * class_c: inherits from class_b
+ */
+typedef struct class_c
+{
+ unsigned int hashkey;
+ unsigned short obj_type;
+ unsigned short class_id;
+ struct objmask* 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), 410, 0);
+ 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), 411);
+ newobj->numitems = origobj->numitems;
+ memcpy(newobj->intarray, origobj->intarray, origobj->numitems * sizeof(int));
+ }
+
+ return newobj;
+}
+
+
+/**
+ * class_c constructor
+ */
+class_c* new_class_c(class_b* parent)
+{
+ int i = 0;
+ class_c* newobj = (class_c*) new_object(sizeof(class_b), 400, 0);
+ 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), 401);
+ for(; i < 4; i++) newobj->intarray[i] = i;
+
+ return newobj;
+}
+
+
+/**
+ * test_inheritance()
+ * test that in scenario c inherits from b inherits from a,
+ * destroying c destroys b destroys a.
+ */
+void test_inheritance(void)
+{
+ class_a* class_toplevel = NULL;
+ class_b* class_midlevel = NULL;
+ class_c* class_lowlevel = NULL;
+
+ class_toplevel = new_class_a(L"it works!");
+ class_midlevel = new_class_b(class_toplevel, 128);
+ class_lowlevel = new_class_c(class_midlevel);
+
+ /* any object destructor should recursively destroy() its superclasses */
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_lowlevel->parent);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_midlevel->parent);
+ CU_ASSERT_PTR_NULL_FATAL(class_toplevel->parent);
+
+ class_lowlevel->destroy(class_lowlevel);
+
+ 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_clone()
+ * test validity of cloned objects, also test construction of inherited object
+ * when the parent(s) implementation(s) is/are not specified.
+ * clones must be disposable, i.e. they must own all their memory
+ * including that of their superclasses, such that if c inherits from b
+ * inherits from a, and I clone c giving c', and I then destroy c, then
+ * I can subsequently destroy c' via normal channels.
+ */
+void test_clone(void)
+{
+ class_c* class_lowlevel = NULL;
+ class_b* class_midlevel = NULL;
+ class_a* class_toplevel = NULL;
+
+ class_c* clone_lowlevel = NULL;
+ class_b* clone_midlevel = NULL;
+ class_a* clone_toplevel = NULL;
+
+ /* construct class c and all its superclasses */
+ class_lowlevel = new_class_c(NULL);
+
+ /* verify that superclasses were created */
+ class_midlevel = (class_b*) class_lowlevel->parent;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_midlevel);
+ class_toplevel = (class_a*) class_midlevel->parent;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(class_toplevel);
+ CU_ASSERT_PTR_NULL_FATAL(class_toplevel->parent);
+
+ /* clone class c and all its superclasses */
+ clone_lowlevel = class_lowlevel->clone(class_lowlevel);
+
+ /* verify that superclasses were created */
+ clone_midlevel = (class_b*) clone_lowlevel->parent;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(clone_midlevel);
+ clone_toplevel = (class_a*) clone_midlevel->parent;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(clone_toplevel);
+ CU_ASSERT_PTR_NULL_FATAL(clone_toplevel->parent);
+
+ /* verify that superclass and data clones are not references to old memory */
+ CU_ASSERT_NOT_EQUAL_FATAL(class_midlevel, clone_midlevel);
+ CU_ASSERT_NOT_EQUAL_FATAL(class_toplevel, clone_toplevel);
+
+ if (class_midlevel->data != 0 && clone_midlevel->data != 0)
+ CU_ASSERT_NOT_EQUAL_FATAL(class_midlevel->data, clone_midlevel->data);
+ if (class_toplevel->a_string != 0 && clone_toplevel->a_string != 0)
+ CU_ASSERT_NOT_EQUAL_FATAL(class_toplevel->a_string, clone_toplevel->a_string);
+
+ /* we don't need to do this for the test, but here we illustrate
+ * the etch C way of accessing superclass data from a subclass,
+ * which is to traverse the parent chain to the class you want,
+ * and cast the parent* to that class, if it is not so cast already.
+ */
+ clone_midlevel->datasize = 1024;
+ clone_midlevel->data = etch_malloc(clone_midlevel->datasize, 419);
+ memset(clone_midlevel->data, '-', clone_midlevel->datasize);
+
+ /* destroy class c with all its superclasses and associated instance data */
+ class_lowlevel->destroy(class_lowlevel);
+
+ /* destroy class c clone and all its superclasses
+ * if the clone of class_c had not properly cloned all its superclasses and
+ * data, this would crash on attempt to free dangling pointer.
+ */
+ clone_lowlevel->destroy(clone_lowlevel);
+
+ 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 */
+}
+
+
+void test_primitive_byte(void)
+{
+ signed char v = 255;
+ etch_byte* newobj = new_byte(v);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(v, newobj->value);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_bool(void)
+{
+ etch_boolean* newobj = new_boolean(100);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(newobj->value, TRUE);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_int8(void)
+{
+ signed char v = -1;
+ etch_int8* newobj = new_int8(v);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(newobj->value,v);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_int16(void)
+{
+ short v = -1;
+ etch_int16* newobj = new_int16(v);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(newobj->value,v);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_int32(void)
+{
+ int v = 1 << 31;
+ etch_int32* newobj = new_int32(v);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(newobj->value,v);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_int64(void)
+{
+ int64 v = ((int64)(1)) << 63;
+ etch_int64* newobj = new_int64(v);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(newobj->value,v);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_float(void)
+{
+ float v = (float)(3.14159);
+ etch_float* newobj = new_float(v);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(newobj->value,v);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_double(void)
+{
+ double v = (1 << 31) + 3.14159;
+ etch_double* newobj = new_double(v);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(newobj->value,v);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+void test_primitive_string(void)
+{
+ wchar_t* v = L"it works!";
+ etch_string* newobj = new_string(v, ETCH_ENCODING_UTF16);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(newobj);
+ CU_ASSERT_EQUAL(wcscmp(v, newobj->v.valw), 0);
+
+ newobj->destroy(newobj);
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_nativearray_ctordtor()
+ * test that we can create and destroy an etch_nativearray with all memory accounted for
+ */
+void test_nativearray_ctordtor(void)
+{
+ etch_nativearray* bytearray_1x4 = new_nativearray(CLASSID_ARRAY_BYTE, sizeof(byte), 1, 4, 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(bytearray_1x4);
+
+ bytearray_1x4->destroy(bytearray_1x4);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_nativearray_1x1x4()
+ * test that we can populate and access a 1-dimensional array of byte
+ */
+void test_nativearray_1x1x4(void)
+{
+ int i = 0, result = 0;
+ char x[4] = {'a','b','c','d'}, thisx = 0;
+ const int numdimensions = 1, itemcount = 4;
+
+ etch_nativearray* a = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, itemcount, 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+
+ for(i = 0; i < itemcount; i++) /* populate array */
+ {
+ result = a->put1(a, &x[i], i); /* insert value of i to ith slot */
+ CU_ASSERT_EQUAL(result, 0);
+ }
+
+ for(i = 0; i < itemcount; i++) /* read values out of array */
+ {
+ result = a->get1(a, &thisx, i); /* get value of ith slot into thisx */
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(x[i], thisx);
+ }
+
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_nativearray_1x4x4()
+ * test that we can populate and access a 1-dimensional array of int
+ */
+void test_nativearray_1x4x4(void)
+{
+ int i = 0, j = 0, result = 0;
+ const int numdimensions = 1, itemcount = 4;
+
+ etch_nativearray* a = new_nativearray
+ (CLASSID_ARRAY_INT32, sizeof(int), numdimensions, itemcount, 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+
+ for(i = 0; i < itemcount; i++) /* populate array */
+ {
+ result = a->put1(a, &i, i); /* insert value of i to ith slot */
+ CU_ASSERT_EQUAL(result, 0);
+ }
+
+ for(i = 0; i < itemcount; i++) /* read values out of array */
+ {
+ result = a->get1(a, &j, i); /* get value of ith slot into j */
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(i, j);
+ }
+
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_nativearray_1xstruct()
+ * test that we can populate and access a 1-dimensional array of struct
+ */
+void test_nativearray_1xstruct(void)
+{
+ int i = 0, result = 0;
+ const int numdimensions = 1, itemcount = 4;
+ struct x { int n; char c; };
+ struct x xgot = {-1,'?'};
+ struct x xs[4] = { {0,'a'}, {1,'b'}, {2,'c'}, {3,'d'}, };
+
+ etch_nativearray* a = new_nativearray
+ (CLASSID_ARRAY_STRUCT, sizeof(struct x), numdimensions, itemcount, 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+
+ for(i = 0; i < itemcount; i++) /* populate array */
+ {
+ result = a->put1(a, &xs[i], i); /* insert xs[i] to ith slot */
+ CU_ASSERT_EQUAL(result, 0);
+ }
+
+ for(i = 0; i < itemcount; i++) /* read values out of array */
+ {
+ result = a->get1(a, &xgot, i); /* get value of ith slot into xgot */
+ CU_ASSERT_EQUAL(result, 0);
+ result = memcmp(&xgot, &xs[i], sizeof(struct x));
+ CU_ASSERT_EQUAL(result, 0);
+ }
+
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_nativearray_2x1x4()
+ * test that we can populate and access a 2-dimensional array of byte
+ */
+void test_nativearray_2x1x4(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;
+
+ /* note when creating arrays, the dimensions are specified in reverse,
+ * low-order dimension (dim0) first, e.g., for x[2][3][4],
+ * dim0count is 4, dim1count is 3, dim2count is 2.
+ */
+ etch_nativearray* a = new_nativearray
+ (CLASSID_ARRAY_BYTE, sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+
+ for(i = 0; i < dim1count; i++) /* populate array */
+ {
+ for(j = 0; j < dim0count; j++)
+ { /* insert x[i][j] to array[i][j] */
+ result = a->put2(a, &x[i][j], i, j);
+ CU_ASSERT_EQUAL(result, 0);
+ }
+ }
+
+ for(i = 0; i < dim1count; i++) /* read array */
+ {
+ for(j = 0; j < dim0count; j++) /* read values out of array */
+ { /* get array[i][j] into thisx */
+ result = a->get2(a, &thisx, i, j);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(x[i][j], thisx);
+ }
+ }
+
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_nativearray_3xstruct()
+ * test that we can populate and access a 3-dimensional array of struct
+ */
+void test_nativearray_3xstruct(void)
+{
+ int i = 0, j = 0, k = 0, result = 0;
+ struct x { int n; char c; };
+ struct x xgot = {-1,'?'};
+ struct x *xthis = 0;
+
+ struct x xs[2][3][4] =
+ {
+ {
+ {
+ {0,'a'}, {1,'b'}, {2,'c'}, {3,'d'},
+ },
+ {
+ {0,'e'}, {1,'f'}, {2,'g'}, {3,'h'},
+ },
+ {
+ {0,'i'}, {1,'j'}, {2,'k'}, {3,'l'},
+ },
+ },
+ {
+ {
+ {0,'m'}, {1,'n'}, {2,'o'}, {3,'p'},
+ },
+ {
+ {0,'q'}, {1,'r'}, {2,'s'}, {3,'t'},
+ },
+ {
+ {0,'u'}, {1,'v'}, {2,'w'}, {3,'x'},
+ },
+ },
+ };
+
+ const int numdimensions = 3, dim0count = 4, dim1count = 3, dim2count = 2;
+
+ etch_nativearray* a = new_nativearray (CLASSID_ARRAY_STRUCT, sizeof(struct x),
+ numdimensions, dim0count, dim1count, dim2count);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+
+ for(i = 0; i < dim2count; i++) /* write array */
+ {
+ for(j = 0; j < dim1count; j++)
+ {
+ for(k = 0; k < dim0count; k++)
+ {
+ result = a->put3(a, &xs[i][j][k], i, j, k);
+ CU_ASSERT_EQUAL(result, 0);
+ }
+ }
+ }
+
+ for(i = 0; i < dim2count; i++) /* read array */
+ {
+ for(j = 0; j < dim1count; j++)
+ {
+ for(k = 0; k < dim0count; k++)
+ {
+ result = a->get3(a, &xgot, i, j, k);
+ CU_ASSERT_EQUAL(result, 0);
+ xthis = &xs[i][j][k];
+ result = memcmp(&xgot, xthis, sizeof(struct x));
+ CU_ASSERT_EQUAL(result, 0);
+ }
+ }
+ }
+
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_arrayfrom_2x1x4()
+ * test that we can access a static 2-dimensional array of byte.
+ * also validates that our array subscripting calculations match those of
+ * the C compiler, since we map and access an array mapped by the compiler.
+ * also validates that the etch_nativearray will not attempt to destroy
+ * the byte vector of an array created in this manner.
+ */
+void test_arrayfrom_2x1x4(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;
+
+ etch_nativearray* a = new_nativearray_from(&x, CLASSID_ARRAY_BYTE,
+ sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+
+ for(i = 0; i < dim1count; i++) /* read array */
+ {
+ for(j = 0; j < dim0count; j++) /* read values out of array */
+ { /* get array[i][j] into thisx */
+ result = a->get2(a, &thisx, i, j);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(x[i][j], thisx);
+ }
+ }
+
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * test_subarray()
+ * test that we can create a one-dimensional subarray from a 2-dimensional
+ * array of byte, and that all memory is accounted for.
+ */
+void test_subarray(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;
+ etch_nativearray *a0 = NULL, *a1 = NULL, *a2 = NULL;
+
+ etch_nativearray* a = new_nativearray_from(&x, CLASSID_ARRAY_BYTE,
+ sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+ a->content_obj_type = ETCHTYPEB_BYTE;
+ a->content_class_id = CLASSID_NONE; /* unwrapped content */
+
+ a0 = new_subarray(a, 0); /* test index 0 */
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a0);
+
+ CU_ASSERT_EQUAL(a0->is_content_owned, FALSE);
+ CU_ASSERT_EQUAL(a0->numdims, a->numdims-1);
+ CU_ASSERT_EQUAL(a0->bytecount, a->bytecount/2);
+ CU_ASSERT_EQUAL(a0->itemsize, a->itemsize);
+
+ CU_ASSERT_EQUAL(a0->content_obj_type, a->content_obj_type);
+ CU_ASSERT_EQUAL(a0->content_class_id, a->content_class_id);
+
+ /* recall that dimension and dimsize are stored low-order
+ * dimension first, so dimension[0] and dimsize[0] are
+ * the same for byte x[2][4] as for x[4] */
+ CU_ASSERT_EQUAL(a0->dimension[0], a->dimension[0]);
+ CU_ASSERT_EQUAL(a0->dimsize[0], a->dimsize[0]);
+
+ for(i = 0; i < dim0count; i++)
+ {
+ result = a0->get1(a0, &thisx, i);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(x[0][i], thisx);
+ }
+
+ a1 = new_subarray(a, 1); /* test index 1 */
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a1);
+
+ CU_ASSERT_EQUAL(a1->is_content_owned, FALSE);
+ CU_ASSERT_EQUAL(a1->numdims, a->numdims-1);
+ CU_ASSERT_EQUAL(a1->bytecount, a->bytecount/2);
+ CU_ASSERT_EQUAL(a1->itemsize, a->itemsize);
+
+ CU_ASSERT_EQUAL(a1->content_obj_type, a->content_obj_type);
+ CU_ASSERT_EQUAL(a1->content_class_id, a->content_class_id);
+
+ /* recall that dimension and dimsize are stored low-order
+ * dimension first, so dimension[0] and dimsize[0] are
+ * the same for byte x[2][4] as for x[4] */
+ CU_ASSERT_EQUAL(a1->dimension[0], a->dimension[0]);
+ CU_ASSERT_EQUAL(a1->dimsize[0], a->dimsize[0]);
+
+ for(i = 0; i < dim0count; i++)
+ {
+ result = a1->get1(a1, &thisx, i);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(x[1][i], thisx);
+ }
+
+ a2 = new_subarray(a, 2); /* test nonexistent index 2 */
+ CU_ASSERT_PTR_NULL(a2);
+
+ a1->destroy(a1);
+ a0->destroy(a0);
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/*
+ * test_if_busted_subarray()
+ * this test is here to debug something that was either broken in subarray,
+ * or that was not broken, but rather the validator test using it was broken.
+ * verdict: subarray itemsize was broken, is fixed.
+ */
+void test_if_busted_subarray(void)
+{
+ short x[2][3][4] =
+ { { { 1,1,1,1, }, { 1,1,1,1, }, { 1,-1,32767, -32768, }, },
+ { { 1,1,1,1, }, { 1,1,1,1, }, { 1,-1,0xfffe,0xffff, }, },
+ };
+ const int numdimensions = 3, dim0count = 4, dim1count = 3, dim2count = 2;
+ int i=0, j=0, k=0;
+
+ etch_nativearray* a1 = new_nativearray_from(&x, CLASSID_ARRAY_INT16,
+ sizeof(short), numdimensions, dim0count, dim1count, dim2count);
+ a1->content_obj_type = ETCHTYPEB_INT16;
+ a1->content_class_id = CLASSID_NONE; /* unwrapped */
+
+ for(i = 0; i < dim2count; i++)
+ {
+ etch_nativearray* a2 = (etch_nativearray*) etch_nativearray_get_element(a1, i);
+ CU_ASSERT_EQUAL_FATAL(is_etch_nativearray(a2), TRUE);
+ CU_ASSERT_EQUAL_FATAL(a2->bytecount, a1->bytecount/a1->dimension[2]);
+ CU_ASSERT_EQUAL_FATAL(a2->numdims, a1->numdims-1);
+ CU_ASSERT_EQUAL_FATAL(a2->dimsize[0], a1->dimsize[0]);
+ CU_ASSERT_EQUAL_FATAL(a2->dimsize[1], a1->dimsize[1]);
+ CU_ASSERT_EQUAL_FATAL(a2->dimension[0],a1->dimension[0]);
+ CU_ASSERT_EQUAL_FATAL(a2->dimension[1],a1->dimension[1]);
+ CU_ASSERT_EQUAL_FATAL(a2->dimension[1],dim1count);
+
+ for(j = 0; j < dim1count; j++)
+ {
+ etch_nativearray* a3 = (etch_nativearray*) etch_nativearray_get_element(a2, j);
+ CU_ASSERT_EQUAL_FATAL(is_etch_nativearray(a3), TRUE);
+ CU_ASSERT_EQUAL_FATAL(a3->bytecount, a2->bytecount/a2->dimension[1]);
+ CU_ASSERT_EQUAL_FATAL(a3->numdims, a2->numdims-1);
+ CU_ASSERT_EQUAL_FATAL(a3->dimsize[0], a2->dimsize[0]);
+ CU_ASSERT_EQUAL_FATAL(a3->dimension[0],a2->dimension[0]);
+ CU_ASSERT_EQUAL_FATAL(a3->dimension[0],dim0count);
+
+ for(k = 0; k < dim0count; k++)
+ {
+ short n_expected = 0, n_actual = 0;
+ etch_int16* shortobj = (etch_int16*) etch_nativearray_get_element(a3, k);
+ CU_ASSERT_EQUAL_FATAL(is_etch_int16(shortobj), TRUE);
+ n_expected = x[i][j][k];
+ n_actual = shortobj->value;
+ CU_ASSERT_EQUAL_FATAL(n_expected, n_actual);
+
+ shortobj->destroy(shortobj);
+ }
+
+ a3->destroy(a3);
+ }
+
+ a2->destroy(a2);
+ }
+
+ a1->destroy(a1);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_get_element()
+ * test that we can get element[i] of a native array, and that element
+ * is another native array, or a wrapped etch object the same type as
+ * the array's content_obj_type and possibly content_class_id.
+ */
+void test_get_element(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;
+ etch_nativearray *a1 = NULL;
+ objmask* returnobj = NULL;
+ etch_byte* retbyteobj = NULL;
+
+ etch_nativearray* a = new_nativearray_from(&x, CLASSID_ARRAY_BYTE,
+ sizeof(byte), numdimensions, dim0count, dim1count, 0);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(a);
+ a->content_obj_type = ETCHTYPEB_BYTE;
+ a->content_class_id = CLASSID_NONE; /* unwrapped content */
+
+ /* get element[1] from the array, expecting a byte[4] native array */
+ returnobj = etch_nativearray_get_element(a, 1);
+
+ CU_ASSERT_EQUAL_FATAL(is_etch_nativearray(returnobj), TRUE);
+
+ a1 = (etch_nativearray*) returnobj;
+
+ CU_ASSERT_EQUAL(a1->is_content_owned, FALSE);
+ CU_ASSERT_EQUAL(a1->numdims, a->numdims-1);
+ CU_ASSERT_EQUAL(a1->bytecount, a->bytecount/2);
+ CU_ASSERT_EQUAL(a1->itemsize, a->itemsize);
+
+ CU_ASSERT_EQUAL(a1->content_obj_type, a->content_obj_type);
+ CU_ASSERT_EQUAL(a1->content_class_id, a->content_class_id);
+ CU_ASSERT_EQUAL(a1->dimension[0], a->dimension[0]);
+ CU_ASSERT_EQUAL(a1->dimsize[0], a->dimsize[0]);
+
+ for(i = 0; i < dim0count; i++)
+ {
+ /* get element[i] from the subarray, expecting an etch_byte object */
+ returnobj = etch_nativearray_get_element(a1, i);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(returnobj);
+ CU_ASSERT_EQUAL_FATAL(returnobj->class_id, CLASSID_PRIMITIVE_BYTE);
+
+ retbyteobj = (etch_byte*) returnobj; /* verify that wrapped byte */
+ thisx = retbyteobj->value; /* matches original array */
+ CU_ASSERT_EQUAL(x[1][i], thisx);
+
+ retbyteobj->destroy(retbyteobj);
+ }
+
+ a1->destroy(a1);
+ a->destroy(a);
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear();
+}
+
+
+/**
+ * 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 primitive byte", test_primitive_byte);
+ CU_add_test(ps, "test primitive boolean", test_primitive_bool);
+ CU_add_test(ps, "test primitive int8", test_primitive_int8);
+ CU_add_test(ps, "test primitive int16", test_primitive_int16);
+ CU_add_test(ps, "test primitive int32", test_primitive_int32);
+ CU_add_test(ps, "test primitive int64", test_primitive_int64);
+ CU_add_test(ps, "test primitive float", test_primitive_float);
+ CU_add_test(ps, "test primitive double", test_primitive_double);
+ CU_add_test(ps, "test primitive string", test_primitive_string);
+
+ CU_add_test(ps, "test tri-level inheritance", test_inheritance);
+ CU_add_test(ps, "test clone and auto-construct superclass", test_clone);
+
+ CU_add_test(ps, "test native array ctor", test_nativearray_ctordtor);
+ CU_add_test(ps, "test 1-dim byte array", test_nativearray_1x1x4);
+ CU_add_test(ps, "test 1-dim int array", test_nativearray_1x4x4);
+ CU_add_test(ps, "test 1-dim struct array", test_nativearray_1xstruct);
+ CU_add_test(ps, "test 2-dim byte array", test_nativearray_2x1x4);
+ CU_add_test(ps, "test 3-dim struct array", test_nativearray_3xstruct);
+ CU_add_test(ps, "test static 2-dim byte array", test_arrayfrom_2x1x4);
+ CU_add_test(ps, "test subarray", test_subarray);
+ CU_add_test(ps, "test get array element", test_get_element);
+ CU_add_test(ps, "test 3-dim int16 subarray ", test_if_busted_subarray);
+
+ 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_flexbuf.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_flexbuf.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_flexbuf.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_flexbuf.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,463 @@
+/* $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_flexbuf.c
+ * test flex buffer
+ */
+#include "apr_time.h" /* some apr must be included first */
+#include "etchthread.h"
+#include <limits.h>
+#include <float.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <conio.h>
+
+#include "cunit.h"
+#include "basic.h"
+#include "automated.h"
+
+#include "etchflexbuf.h"
+#include "etch_global.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;
+}
+
+etch_flexbuffer* fbuf = 0;
+
+
+/**
+ * returns number of errors
+ */
+int check_buf(etch_flexbuffer* buf, const int len, const int ndx, const int avl)
+{
+ int errors = 0, avail = (int) etch_flexbuf_avail(buf);
+ if (buf->datalen != len) errors++;
+ if (buf->index != ndx) errors++;
+ if (avail != avl) errors++;
+ return errors;
+}
+
+void testCreateAndDestroy0(void)
+{
+ fbuf = new_flexbuffer(0);
+ CU_ASSERT_PTR_NOT_NULL(fbuf);
+
+ CU_ASSERT(etch_flexbuf_avail(fbuf) == 0);
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+void testCreateAndDestroy1(void)
+{
+ fbuf = new_flexbuffer(-1);
+ CU_ASSERT_PTR_NOT_NULL(fbuf);
+
+ fbuf = new_flexbuffer(1);
+ CU_ASSERT_PTR_NOT_NULL(fbuf);
+ CU_ASSERT(etch_flexbuf_avail(fbuf) == 0);
+
+ destroy_etch_flexbuffer(fbuf);
+
+ fbuf = new_flexbuffer(4*1024*1024+1);
+ CU_ASSERT_PTR_NOT_NULL(fbuf);
+ destroy_etch_flexbuffer(fbuf); /* takes NULL */
+}
+
+void testCreateAndDestroy2(void)
+{
+ void *ptr = etch_malloc(1024, 0);
+ fbuf = etch_flexbuf_create_b(ptr, 1024, 0);
+ CU_ASSERT_PTR_NOT_NULL(fbuf);
+ CU_ASSERT(etch_flexbuf_avail(fbuf) == 0);
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+void testCreateAndDestroy3(void)
+{
+ void *ptr = etch_malloc(1024, 0);
+ fbuf = etch_flexbuf_create_bi(ptr, 1024, 100, 0);
+ CU_ASSERT_PTR_NOT_NULL(fbuf);
+ CU_ASSERT(etch_flexbuf_avail(fbuf) == 100);
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+void testPutAndGet(void)
+{
+ byte test_bytes[] = "testbytes";
+ void *test_buffer = etch_malloc(128, 0);
+ size_t n;
+ int i;
+ etch_flexbuffer *efb2;
+
+ fbuf = new_flexbuffer(0);
+
+ etch_flexbuf_put(fbuf, test_bytes, 0, strlen(test_bytes));
+
+ /* rewind the buffer */
+ etch_flexbuf_set_index(fbuf, 0);
+ n = etch_flexbuf_get(fbuf, test_buffer, 0, strlen(test_bytes));
+ CU_ASSERT(memcmp(test_buffer, test_bytes, n) == 0);
+
+ /* test put byte */
+ etch_flexbuf_set_index(fbuf, 0);
+ for(i = 0; i < (int) strlen(test_bytes); i++)
+ etch_flexbuf_put_byte(fbuf, test_bytes[i]);
+
+ etch_flexbuf_set_index(fbuf, 0);
+ n = etch_flexbuf_get(fbuf, test_buffer, 0, strlen(test_bytes));
+ CU_ASSERT(memcmp(test_buffer, test_bytes, n) == 0);
+
+ /* test put from another buffer */
+ efb2 = new_flexbuffer(0);
+ etch_flexbuf_set_index(fbuf, 0);
+ etch_flexbuf_put_from(efb2, fbuf, n);
+
+ etch_flexbuf_set_index(efb2, 0);
+ n = etch_flexbuf_get(efb2, test_buffer, 0, strlen(test_bytes));
+ CU_ASSERT(memcmp(test_buffer, test_bytes, n) == 0);
+
+ etch_free(test_buffer);
+ destroy_etch_flexbuffer(fbuf);
+ destroy_etch_flexbuffer(efb2);
+}
+
+void testPutAndGetFully(void)
+{
+ byte test_bytes[] = "testbytes";
+ void *test_buffer = etch_malloc(128, 0);
+ size_t n;
+
+ fbuf = new_flexbuffer(0);
+
+ etch_flexbuf_put(fbuf, test_bytes, 0, strlen(test_bytes));
+
+ /* rewind the buffer */
+ etch_flexbuf_set_index(fbuf, 0);
+ n = etch_flexbuf_get_fully(fbuf, test_buffer, strlen(test_bytes));
+ CU_ASSERT(memcmp(test_buffer, test_bytes, n) == 0);
+
+ etch_flexbuf_set_index(fbuf, 0);
+ n = etch_flexbuf_get_fully(fbuf, test_buffer, 4);
+ CU_ASSERT(memcmp(test_buffer, test_bytes, 4) == 0);
+
+ etch_flexbuf_set_index(fbuf, 0);
+ n = etch_flexbuf_get_fully(fbuf, test_buffer, 32);
+ CU_ASSERT(memcmp(test_buffer, test_bytes, min(strlen(test_bytes), 32)) == 0);
+
+ etch_free(test_buffer);
+ destroy_etch_flexbuffer(fbuf);
+}
+
+
+void testPutAndGetByte(void)
+{
+ byte test_bytes[] = "testbytes";
+ void *test_buffer = etch_malloc(128, 0);
+ size_t n;
+ int i;
+
+ fbuf = new_flexbuffer(0);
+
+ etch_flexbuf_set_index(fbuf, 0);
+ for(i = 0; i < (int)strlen(test_bytes); i++)
+ etch_flexbuf_put_byte(fbuf, test_bytes[i]);
+
+ etch_flexbuf_set_index(fbuf, 0);
+ n = etch_flexbuf_get(fbuf, test_buffer, 0, strlen(test_bytes));
+ CU_ASSERT(memcmp(test_buffer, test_bytes, n) == 0);
+
+
+ etch_free(test_buffer);
+ destroy_etch_flexbuffer(fbuf);
+}
+
+void testPutAndGetShort(void)
+{
+ short test_shorts[] = {SHRT_MIN, SHRT_MAX, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0x7FFF, \
+ 0xFFFF, 0xFFFE, -8192, -4096, -2048, -1024, -512, -256, -128, -64, -32, -16, -8, -4, -2, -1};
+
+ int i, result; short value = 0;
+
+ fbuf = new_flexbuffer(0);
+
+ for(i = 0; i < sizeof(test_shorts)/sizeof(short); i++)
+ etch_flexbuf_put_short(fbuf, test_shorts[i]);
+
+ etch_flexbuf_set_index(fbuf, 0);
+
+ for(i = 0; i < sizeof(test_shorts)/sizeof(short); i++)
+ {
+ result = etch_flexbuf_get_short(fbuf, &value);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(test_shorts[i], value);
+ }
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+
+void testPutAndGetInt(void)
+{
+ int test_ints[] = {INT_MIN, INT_MAX, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0x7FFF, \
+ 0xFFFF, 0xFFFFF, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFFE,0x7FFFFFFF, 0xFFFFFFFF, 0xF7FFFFFF, 0xF6FFFFFF, \
+ 0xF5FFFFFF, 0xF4FFFFFF, 0xF3FFFFFF, 0xF2FFFFFF, 0xF1FFFFFF, 0xF0FFFFFF, 0xFF0FFFFF, \
+ -8192, -4096, -2048, -1024, -512, -256, -128, -64, -32, -16, -8, -4, -2, -1};
+
+ int i;
+
+ fbuf = new_flexbuffer(0);
+
+ for(i = 0; i < sizeof(test_ints)/sizeof(int); i++)
+ etch_flexbuf_put_int(fbuf, test_ints[i]);
+
+ etch_flexbuf_set_index(fbuf, 0);
+ for(i = 0; i < sizeof(test_ints)/sizeof(int); i++)
+ {
+ int n = 0, m = test_ints[i], result;
+ result = etch_flexbuf_get_int(fbuf, &n);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(n,m);
+ }
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+
+void testPutAndGetInt64(void)
+{
+ int64 test_int64s[] = {LONG_MIN, LONG_MAX, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0x7FFF, \
+ 0xFFFF, 0xFFFFF, 0xFFFFFF, 0xFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xF7FFFFFF, 0xF6FFFFFF, 0x7FFFFFFFFFFFFFFF,\
+ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFF0, 0xFFFFFFFFFFFFFF00, 0xFFFFFFFFFFFFF000, 0xFFFFFFFFFFFFF000, \
+ 0xF5FFFFFF, 0xF4FFFFFF, 0xF3FFFFFF, 0xF2FFFFFF, 0xF1FFFFFF, 0xF0FFFFFF, 0xFF0FFFFF, \
+ -8192, -4096, -2048, -1024, -512, -256, -128, -64, -32, -16, -8, -4, -2, -1};
+
+ int i, result;
+
+ fbuf = new_flexbuffer(0);
+
+ for(i = 0; i < sizeof(test_int64s)/sizeof(int64); i++)
+ etch_flexbuf_put_long(fbuf, test_int64s[i]);
+
+ etch_flexbuf_set_index(fbuf, 0);
+
+ for(i = 0; i < sizeof(test_int64s)/sizeof(int64); i++)
+ {
+ int64 n = 0, m = test_int64s[i];
+ result = etch_flexbuf_get_long(fbuf, &n);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(n,m);
+ }
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+
+void testPutAndGetFloat(void)
+{
+ float test_floats[] = {FLT_MIN, 0.0f, 1.1f, 2.2f, 4.4f, 8.8f, 16.16f, 32.32f, 64.64f, 128.128f, 256.256f, 512.512f,\
+ 1024.1024f, 2048.2048f, 4096.4096f, 8192.8192f, FLT_MAX};
+
+ int i, result;
+
+ fbuf = new_flexbuffer(0);
+
+ for(i = 0; i < sizeof(test_floats)/sizeof(float); i++)
+ etch_flexbuf_put_float(fbuf, test_floats[i]);
+
+ etch_flexbuf_set_index(fbuf, 0);
+
+ for(i = 0; i < sizeof(test_floats)/sizeof(float); i++)
+ {
+ float x = 0.0; double diff; int is_equal;
+ const float y = test_floats[i];
+ result = etch_flexbuf_get_float(fbuf, &x);
+ CU_ASSERT_EQUAL(result, 0);
+ diff = (double) (y - x);
+ is_equal = fabs(diff) < 0.00001;
+ CU_ASSERT_EQUAL(is_equal, TRUE);
+ }
+
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+void testPutAndGetDouble(void)
+{
+ double test_doubles[] = {DBL_MIN, 0.0, 1.1, 2.2, 4.4, 8.8, 16.16, 32.32, 64.64, 128.128, 256.256, 512.512,\
+ 1024.1024, 2048.2048, 4096.4096, 8192.8192, DBL_MAX};
+
+ int i, result;
+
+ fbuf = new_flexbuffer(0);
+
+ for(i = 0; i < sizeof(test_doubles)/sizeof(double); i++)
+ etch_flexbuf_put_double(fbuf, test_doubles[i]);
+
+ etch_flexbuf_set_index(fbuf, 0);
+
+ for(i = 0; i < sizeof(test_doubles)/sizeof(double); i++)
+ {
+ double x, y = test_doubles[i];
+ result = etch_flexbuf_get_double(fbuf, &x);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT(x == y);
+ }
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+void testSetSize(void)
+{
+ etch_flexbuffer *fbuf = new_flexbuffer(0);
+
+ CU_ASSERT_EQUAL(0, etch_flexbuf_set_length(fbuf, 1024));
+ CU_ASSERT_EQUAL(0, check_buf(fbuf, 1024, 0, 1024));
+
+ CU_ASSERT_EQUAL(0, etch_flexbuf_set_length(fbuf, 0));
+ CU_ASSERT_EQUAL(0, check_buf(fbuf, 0, 0, 0));
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+void testCompact(void)
+{
+ int i;
+ etch_flexbuffer *fbuf = new_flexbuffer(128);
+
+ for(i = 0; i < 10; i++)
+ etch_flexbuf_put_short(fbuf, 1);
+
+ etch_flexbuf_set_index(fbuf, 0);
+ etch_flexbuf_compact(fbuf);
+ CU_ASSERT(fbuf->index ==0);
+ CU_ASSERT(etch_flexbuf_avail(fbuf) == (10*sizeof(short)));
+
+ destroy_etch_flexbuffer(fbuf);
+}
+
+
+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;
+ ps = CU_add_suite("suite flexbuffer", init_suite, clean_suite);
+ CU_set_output_filename("../test_flexbuffer");
+ etch_watch_id = 0;
+
+ CU_add_test(ps, "testCreateAndDestroy0", testCreateAndDestroy0);
+ CU_add_test(ps, "testCreateAndDestroy1", testCreateAndDestroy1);
+ CU_add_test(ps, "testCreateAndDestroy2", testCreateAndDestroy2);
+ CU_add_test(ps, "testCreateAndDestroy3", testCreateAndDestroy3);
+ CU_add_test(ps, "testPutAndGet", testPutAndGet);
+ CU_add_test(ps, "testPutAndGetFully", testPutAndGetFully);
+ CU_add_test(ps, "testPutAndGetByte", testPutAndGetByte);
+ CU_add_test(ps, "testPutAndGetShort", testPutAndGetShort);
+ CU_add_test(ps, "testPutAndGetInt", testPutAndGetInt);
+ CU_add_test(ps, "testPutAndGetInt64", testPutAndGetInt64);
+ CU_add_test(ps, "testPutAndGetFloat", testPutAndGetFloat);
+ CU_add_test(ps, "testPutAndGetFloat", testPutAndGetDouble);
+ CU_add_test(ps, "testSetSize", testSetSize);
+ CU_add_test(ps, "testCompact", testCompact);
+
+ 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(); printf("\n"); }
+ CU_cleanup_registry();
+ return CU_get_error();
+}
\ No newline at end of file
Added: incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_hashing.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_hashing.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_hashing.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/common/test_hashing.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,430 @@
+/* $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_hashing.c
+ * test hashing of various complex items and associated memory management
+ */
+#include "apr_time.h" /* some apr must be included first */
+#include "etch_binary_tdi.h" /* must be included second */
+#include "etch_binary_tdo.h"
+
+#include <tchar.h>
+#include <stdio.h>
+#include <conio.h>
+
+#include "cunit.h"
+#include "basic.h"
+#include "automated.h"
+
+#include "etch_connection.h"
+#include "etch_global.h"
+#include "etch_id_name.h"
+#include "etch_field.h"
+#include "etch_type.h"
+#include "etchlog.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";
+#define IS_DEBUG_CONSOLE FALSE
+
+
+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;
+}
+
+
+/*
+ * 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;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - -
+ * local declarations
+ * - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+
+/* - - - - - - - - - - - - - - - - - - - - - -
+ * local setup and teardown
+ * - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+int this_setup()
+{
+ etch_apr_mempool = g_apr_mempool;
+ return 0;
+}
+
+int this_teardown()
+{
+ return 0;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - -
+ * individual setup and teardown
+ * - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+int this_test_setup()
+{
+ int result = -1;
+
+ do {
+ result = 0;
+
+ } while(0);
+
+ return result;
+}
+
+int this_test_teardown()
+{
+
+ return 0;
+}
+
+int g_is_automated_test, g_bytes_allocated;
+
+
+/**
+ * destroy_content_id_name()
+ * passed a content pointer out of the hashtable, interprets pointer as etch_id_name,
+ * frees the name string, and frees the etch_id_name shell.
+ */
+int destroy_content_id_name(void* content)
+{
+ etch_id_name* idname = (etch_id_name*) content;
+ return idname? idname->destroy(idname): -1;
+ return 0;
+}
+
+
+/**
+ * destroy_content_field()
+ */
+int destroy_content_field(void* content)
+{
+ etch_field* field = (etch_field*) content;
+ return field? field->destroy(field): -1;
+}
+
+
+/**
+ * destroy_content_type()
+ */
+int destroy_content_type(void* content)
+{
+ etch_type* type = (etch_type*) content;
+ return type? type->destroy(type): -1;
+}
+
+
+/**
+ * test_idname_as_key
+ * tests that we can use etch_id_name (and etch_field and etch_type, since they
+ * are etch_id_name typedefs), as hashkeys, and subsequently acccess the original
+ * objects, individually clean up the keys, and ask hashtable to clean up the values.
+ */
+void test_idname_as_key_hashclean_values(void)
+{
+ etch_field* my_field = NULL;
+ etch_type* my_type = NULL;
+ etch_id_name* my_idname = NULL;
+
+ const int id_name_size = sizeof(etch_id_name);
+ const int field_size = sizeof(etch_field);
+ const int type_size = sizeof(etch_type);
+
+ etch_hashtable* myhashtab = NULL;
+ etch_hashitem hashbucket;
+ etch_hashitem* myentry = &hashbucket;
+
+ wchar_t* name1 = L"name number one";
+ wchar_t* name2 = L"nombre numero dos";
+ wchar_t* name3 = L"le troisieme nom";
+
+ const size_t numElements1 = wcslen(name1);
+ const size_t numElements2 = wcslen(name2);
+ const size_t numElements3 = wcslen(name3);
+
+ const size_t numBytes1 = sizeof(wchar_t) * numElements1;
+ const size_t numBytes2 = sizeof(wchar_t) * numElements2;
+ const size_t numBytes3 = sizeof(wchar_t) * numElements3;
+
+ void* value1 = NULL, *value2 = NULL, *value3 = NULL;
+
+ int result = 0, result1 = 0, result2 = 0, result3 = 0;
+ unsigned bytes_allocated = 0;
+
+ value1 = etch_malloc(numBytes1 + 2, 0);
+ value2 = etch_malloc(numBytes2 + 2, 0);
+ value3 = etch_malloc(numBytes3 + 2, 0);
+ wcscpy_s(value1, numElements1+1, name1);
+ wcscpy_s(value2, numElements2+1, name2);
+ wcscpy_s(value3, numElements3+1, name3);
+
+ myhashtab = new_hashtable(16);
+ myhashtab->is_readonly_keys = TRUE; /* keys will NOT be freed on destroy */
+ myhashtab->is_readonly_values = FALSE; /* values WILL be freed on destroy */
+ myhashtab->is_tracked_memory = TRUE; /* hashtable will use etch_free */
+
+ my_idname = new_id_name(name1);
+ my_field = new_field(name2);
+ my_type = new_type(name3);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_idname);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_field);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_type);
+
+ /* ensure constructors populated the hash key */
+ CU_ASSERT_NOT_EQUAL_FATAL(my_idname->hashkey,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_field->hashkey,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_type->hashkey,0);
+
+ /* ensure constructors populated the wire id */
+ CU_ASSERT_NOT_EQUAL_FATAL(my_idname->id,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_field->id,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_type->id,0);
+
+ result = myhashtab->vtab->inserth(myhashtab->realtable, my_idname, value1, 0, 0);
+ CU_ASSERT_EQUAL_FATAL(result,0);
+
+ result = myhashtab->vtab->inserth(myhashtab->realtable, my_field, value2, 0, 0);
+ CU_ASSERT_EQUAL_FATAL(result,0);
+
+ result = myhashtab->vtab->inserth(myhashtab->realtable, my_type, value3, 0, 0);
+ CU_ASSERT_EQUAL_FATAL(result,0);
+
+ result = myhashtab->vtab->findh(myhashtab->realtable, my_idname->hashkey, myhashtab, &myentry);
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_PTR_NOT_NULL(myentry->key);
+ CU_ASSERT_PTR_NOT_NULL(myentry->value);
+ result = destroy_content_id_name(myentry->key);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = myhashtab->vtab->findh(myhashtab->realtable, my_field->hashkey, myhashtab, &myentry);
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_PTR_NOT_NULL(myentry->key);
+ CU_ASSERT_PTR_NOT_NULL(myentry->value);
+ result = destroy_content_field(myentry->key);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = myhashtab->vtab->findh(myhashtab->realtable, my_type->hashkey, myhashtab, &myentry);
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_PTR_NOT_NULL(myentry->key);
+ CU_ASSERT_PTR_NOT_NULL(myentry->value);
+ result = destroy_content_type(myentry->key);
+ CU_ASSERT_EQUAL(result,0);
+
+ /** above we looked up each item and freed memory for the id_name, field, and type keys,
+ * but not for their values. when we created the map we specified is_readonly_keys, so the
+ * map destructor will free memory for the value content, but not for the key content. */
+ myhashtab->destroy(myhashtab);
+
+ bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_idname_as_key
+ * tests that we can use etch_id_name (and etch_field and etch_type, since they
+ * are etch_id_name typedefs), as hashkeys, and subsequently acccess the original
+ * objects and clean up both the keys and values.
+ */
+void test_idname_as_key_hashclean_none(void)
+{
+ etch_field* my_field = NULL;
+ etch_type* my_type = NULL;
+ etch_id_name* my_idname = NULL;
+
+ const int id_name_size = sizeof(etch_id_name);
+ const int field_size = sizeof(etch_field);
+ const int type_size = sizeof(etch_type);
+
+ etch_hashtable* myhashtab = NULL;
+ etch_hashitem hashbucket;
+ etch_hashitem* myentry = &hashbucket;
+
+ wchar_t* name1 = L"name number one";
+ wchar_t* name2 = L"nombre numero dos";
+ wchar_t* name3 = L"le troisieme nom";
+
+ const size_t numElements1 = wcslen(name1);
+ const size_t numElements2 = wcslen(name2);
+ const size_t numElements3 = wcslen(name3);
+
+ const size_t numBytes1 = sizeof(wchar_t) * numElements1;
+ const size_t numBytes2 = sizeof(wchar_t) * numElements2;
+ const size_t numBytes3 = sizeof(wchar_t) * numElements3;
+ void* value1 = NULL, *value2 = NULL, *value3 = NULL;
+
+ size_t actlen1 = 0, actlen2 = 0, actlen3 = 0;
+ int result = 0, result1 = 0, result2 = 0, result3 = 0;
+ unsigned bytes_allocated = 0;
+
+ value1 = etch_malloc(numBytes1 + 2, 0);
+ value2 = etch_malloc(numBytes2 + 2, 0);
+ value3 = etch_malloc(numBytes3 + 2, 0);
+ wcscpy_s(value1, numElements1+1, name1);
+ wcscpy_s(value2, numElements2+1, name2);
+ wcscpy_s(value3, numElements3+1, name3);
+
+ actlen1 = wcslen(name1); actlen2 = wcslen(name2); actlen3 = wcslen(name3);
+
+ myhashtab = new_hashtable(16);
+ myhashtab->is_readonly_keys = TRUE; /* keys will be freed on destroy */
+ myhashtab->is_readonly_values = TRUE; /* values will be freed on destroy */
+ myhashtab->is_tracked_memory = TRUE; /* hashtable will etch_free content */
+
+ /* here we are creating id_name, field, and type objects using names allocated
+ * on out local stack. therefore the cleanup parameters must be set to not free
+ * memory for the name part, or we will crash. note that name is part of the
+ * key structs, and is also the value of the hashed key/value pair, however
+ * we etch_malloc'ed memory for the values and copied our stack strings into it,
+ * so we will want to free the value memory. we could ask the hashtable to do
+ * so but we'll do it manually here instead.
+ */
+ my_idname = new_id_name(name1);
+ my_field = new_field(name2);
+ my_type = new_type(name3);
+
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_idname);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_field);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_type);
+
+ /* ensure constructors populated the hash key */
+ CU_ASSERT_NOT_EQUAL_FATAL(my_idname->hashkey,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_field->hashkey,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_type->hashkey,0);
+
+ /* ensure constructors populated the id (hash of name) */
+ CU_ASSERT_NOT_EQUAL_FATAL(my_idname->id,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_field->id,0);
+ CU_ASSERT_NOT_EQUAL_FATAL(my_type->id,0);
+
+ result = myhashtab->vtab->inserth(myhashtab->realtable, my_idname, value1, 0, 0);
+ CU_ASSERT_EQUAL_FATAL(result,0);
+
+ result = myhashtab->vtab->inserth(myhashtab->realtable, my_field, value2, 0, 0);
+ CU_ASSERT_EQUAL_FATAL(result,0);
+
+ result = myhashtab->vtab->inserth(myhashtab->realtable, my_type, value3, 0, 0);
+ CU_ASSERT_EQUAL_FATAL(result,0);
+
+ result = myhashtab->vtab->findh(myhashtab->realtable, my_idname->hashkey, myhashtab, &myentry);
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_PTR_NOT_NULL(myentry->key);
+ CU_ASSERT_PTR_NOT_NULL(myentry->value);
+ result = destroy_content_id_name(myentry->key);
+ CU_ASSERT_EQUAL(result,0);
+ etch_free(myentry->value);
+
+ result = myhashtab->vtab->findh(myhashtab->realtable, my_field->hashkey, myhashtab, &myentry);
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_PTR_NOT_NULL(myentry->key);
+ CU_ASSERT_PTR_NOT_NULL(myentry->value);
+ result = destroy_content_field(myentry->key);
+ CU_ASSERT_EQUAL(result,0);
+ etch_free(myentry->value);
+
+ result = myhashtab->vtab->findh(myhashtab->realtable, my_type->hashkey, myhashtab, &myentry);
+ CU_ASSERT_EQUAL(result,0);
+ CU_ASSERT_PTR_NOT_NULL(myentry->key);
+ CU_ASSERT_PTR_NOT_NULL(myentry->value);
+ result = destroy_content_type(myentry->key);
+ CU_ASSERT_EQUAL(result,0);
+ etch_free(myentry->value);
+
+ myhashtab->destroy(myhashtab); /* hashtable was asked to not free any content */
+
+ bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE); /* verify all memory freed */
+ CU_ASSERT_EQUAL(bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ CU_pSuite pSuite = 0; char c=0;
+ if (CUE_SUCCESS != CU_initialize_registry()) return -1;
+ g_is_automated_test = argc > 1 && 0 != wcscmp(argv[1], L"-a");
+ pSuite = CU_add_suite("suite_hashing", init_suite, clean_suite);
+ CU_set_output_filename("../test_hashing");
+ etch_watch_id = 0;
+
+ CU_add_test(pSuite, "test hash id_name etc - auto-cleanup values", test_idname_as_key_hashclean_values);
+ CU_add_test(pSuite, "test hash id_name etc - no auto-cleanup", test_idname_as_key_hashclean_none);
+
+ 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();
+}
+