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 [33/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/transport/test_packetizer.c
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/src/test/transport/test_packetizer.c?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/src/test/transport/test_packetizer.c (added)
+++ incubator/etch/trunk/binding-c/runtime/c/src/test/transport/test_packetizer.c Wed Apr 22 17:25:43 2009
@@ -0,0 +1,2314 @@
+/* $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_packetizer.c
+ */
+
+#include "apr_time.h" /* some apr must be included first */
+#include "etch_packetizer.h" /* must be included second */
+
+#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_encoding.h"
+#include "etchthread.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";
+
+
+/* - - - - - - - - - - - - - -
+ * 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;
+}
+
+/* - - - - - - - - - - - - - -
+ * unit test support
+ * - - - - - - - - - - - - - -
+ */
+
+etch_packetizer* g_my_packetizer;
+i_sessionpacket* g_my_sessionpacket;
+i_transportdata* g_my_transportdata;
+etch_flexbuffer* g_mybuf;
+etch_who* g_who;
+
+#define THISTEST_WHO_VALUE 0x5151
+unsigned short CLASSID_MY_IMPL_SP;
+unsigned short CLASSID_MY_IMPL_TD;
+
+#define is_my_impl_transportdata(x) \
+ (x && ((objmask*)x)->obj_type == ETCHTYPEB_TRANSPORTDATA && ((objmask*)x)->class_id == CLASSID_MY_IMPL_TD)
+
+#define is_my_impl_sessionpkt(x) \
+ (x && ((objmask*)x)->obj_type == ETCHTYPEB_SESSIONPKT&& ((objmask*)x)->class_id == CLASSID_MY_IMPL_SP)
+
+int check_packetizer_results(i_transportdata*, etch_nativearray*);
+int check_packetizer_resultx(i_sessionpacket*, etch_nativearray*);
+int check_packetized_results (etch_arraylist*, etch_nativearray*);
+int check_packetized_result (byte* v1, size_t c1, byte* v2, size_t c2);
+etch_arraylist* new_packetizertest_list();
+
+
+typedef enum etch_what
+{ WHAT_NONE, WHAT_DATA, WHAT_PACKET,
+ TRANSPORT_QUERY, TRANSPORT_CONTROL, TRANSPORT_NOTIFY,
+ SESSION_QUERY, SESSION_CONTROL, SESSION_NOTIFY
+} etch_what;
+
+
+int is_equal_who(etch_who* who1, etch_who* who2)
+{
+ int n1 = 0, n2 = 0;
+ if (!who1 || !who2) return FALSE;
+ if (who1->class_id != CLASSID_WHO || who2->class_id != CLASSID_WHO) return FALSE;
+ if (!who1->value || !who2->value) return FALSE;
+ if (!is_etch_int32(who1->value) || !is_etch_int32(who2->value)) return FALSE;
+ n1 = ((etch_int32*)who1->value)->value;
+ n2 = ((etch_int32*)who2->value)->value;
+ return n1 == n2;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * my_impl_transportdata (i_transportdata implementation)
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * my_impl_transportdata
+ * test object implementing i_transportdata
+ */
+typedef struct my_impl_transportdata
+{
+ 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;
+
+ /* i_transportdata interface and methods, plus original destructor
+ * which becomes replaced with a custom destructor to destroy this
+ * object. this is the model for destroying an interface wrapper object
+ * when we do not save and pass around a pointer to the wrapper, but rather
+ * a pointer to the interface. the interface in question, i_transportdata
+ * in this case, contains a pointer to the wrapper object, in this case a
+ * my_impl_transportdata*. when the interface is instantiated, its original
+ * destructor is saved, and is replaced with a destructor which invokes
+ * the wrapper's destructor. the wrapper destructor must then know to
+ * invoke the interface's original destructor when destroying the interface.
+ */
+ i_transportdata* itd; /* owned */
+ objdtor destroy_transportdata; /* i_transportdata original destructor */
+ etch_transport_data transport_data; /* i_transportdata::transport_data() */
+
+ i_sessiondata* session; /* not owned */
+
+ etch_what what;
+ etch_who* recipient; /* not owned */
+ etch_arraylist* list; /* owned */
+ etch_object* query; /* owned */
+ etch_object* query_result; /* owned */
+ etch_object* control; /* owned */
+ etch_object* value; /* owned */
+ etch_object* eventx; /* owned */
+
+} my_impl_transportdata;
+
+
+/**
+ * destroy_my_impl_transportdata()
+ * my_impl_transportdata destructor
+ */
+int destroy_my_impl_transportdata (my_impl_transportdata* thisx)
+{
+ if (thisx->refcount > 0 && --thisx->refcount > 0) return -1;
+
+ if (!is_etchobj_static_content(thisx))
+ { /* invoke original i_transportdata destructor */
+ if (thisx->itd && thisx->destroy_transportdata)
+ thisx->destroy_transportdata(thisx->itd);
+
+ if (thisx->list)
+ thisx->list->destroy(thisx->list);
+
+ if (thisx->query)
+ thisx->query->destroy(thisx->query);
+
+ if (thisx->query_result)
+ thisx->query_result->destroy(thisx->query_result);
+
+ if (thisx->control)
+ thisx->control->destroy(thisx->control);
+
+ if (thisx->value)
+ thisx->value->destroy(thisx->value);
+
+ if (thisx->eventx)
+ thisx->eventx->destroy(thisx->eventx);
+ }
+
+ return destroy_objectex((objmask*) thisx);
+}
+
+
+
+/**
+ * impl_transport_data()
+ * my_impl_transportdata::transport_data
+ * @param whoto caller retains, can be null
+ * @param fbuf caller retains
+ */
+int impl_transport_data (my_impl_transportdata* mytd, etch_who* whoto, etch_flexbuffer* fbuf)
+{
+ etch_nativearray* wrapped_array = NULL;
+ byte* newbuf = NULL;
+ size_t bytecount = 0;
+
+ assert(is_my_impl_transportdata(mytd));
+ assert(is_etch_transportdata(mytd->itd));
+
+ mytd->what = WHAT_DATA;
+ mytd->recipient = whoto;
+
+ /* get a new byte vector of the entire packet from the buffer */
+ newbuf = etch_flexbuf_get_all (fbuf, &bytecount);
+
+ /* wrap the packet bytes in an etch_nativearray object */
+ wrapped_array = new_nativearray_from (newbuf,
+ CLASSID_ARRAY_BYTE, sizeof(byte), 1, (int) bytecount, 0, 0);
+
+ /* we want wrapped array to own new packet bytes memory */
+ wrapped_array->is_content_owned = TRUE;
+
+ return arraylist_add (mytd->list, wrapped_array);
+}
+
+
+/**
+ * my_transport_control()
+ * my_impl_transportdata::itransport::transport_control
+ */
+int my_transport_control (my_impl_transportdata* mytd, etch_object* control, etch_object* value)
+{
+ /* changed parameter from i_transportdata* to my_impl_transportdata to correspond to change
+ * in etch_pktizer_transport_control to pass pzr->transport->thisx rather than pzr->transport.
+ * likewise for my_transport_notify() and my_transport_query. */
+ CU_ASSERT_FATAL(is_my_impl_transportdata(mytd));
+ mytd->what = TRANSPORT_CONTROL;
+ mytd->control = control;
+ mytd->value = value;
+ return 0;
+}
+
+
+/**
+ * my_transport_notify()
+ * my_impl_transportdata::itransport::transport_notify
+ */
+int my_transport_notify (my_impl_transportdata* mytd, etch_object* evt)
+{
+ CU_ASSERT_FATAL(is_my_impl_transportdata(mytd));
+ mytd->what = TRANSPORT_NOTIFY;
+ mytd->eventx = evt;
+ return 0;
+}
+
+
+/**
+ * my_transport_query()
+ * my_impl_transportdata::itransport::transport_query
+ */
+objmask* my_transport_query (my_impl_transportdata* mytd, etch_object* query)
+{
+ etch_object* resultobj = NULL;
+ CU_ASSERT_FATAL(is_my_impl_transportdata(mytd));
+ resultobj = mytd->query_result; /* set artificially in test */
+ mytd->what = TRANSPORT_QUERY;
+ mytd->query = query;
+ mytd->query_result = NULL;
+ return (objmask*) resultobj; /* caller owns */
+}
+
+
+/**
+ * my_transport_get_session()
+ * my_impl_transportdata::itransport::get_session
+ */
+i_sessiondata* my_transport_get_session (my_impl_transportdata* mytd)
+{
+ ETCH_ASSERT(is_etch_transportdata(mytd));
+ return mytd->session;
+}
+
+
+/**
+ * my_transport_set_session()
+ * my_impl_transportdata::itransport::set_session
+ */
+void my_transport_set_session (my_impl_transportdata* mytd, i_sessiondata* newsession)
+{
+ ETCH_ASSERT(is_etch_transportdata(mytd));
+ ETCH_ASSERT(is_etch_sessiondata(newsession));
+ mytd->session = newsession;
+}
+
+
+/*
+ * destroy_my_transportdata()
+ * i_transportdata destructor
+ * this destructor will destroy its parent (my_impl_transportdata),
+ * which will in turn destroy this object.
+ */
+int destroy_my_transportdata(i_transportdata* itd)
+{
+ my_impl_transportdata* mytd = NULL;
+ if (NULL == itd) return -1;
+
+ mytd = itd->thisx;
+
+ mytd->destroy(mytd);
+
+ return 0;
+}
+
+
+/**
+ * new_my_impl_transportdata()
+ * my_impl_transportdata constructor
+ */
+my_impl_transportdata* new_my_impl_transportdata()
+{
+ i_transportdata* itd = NULL;
+ i_transport* itransport = NULL;
+ /* this is a model for dynamic class ID assigment */
+ unsigned short class_id = CLASSID_MY_IMPL_TD? CLASSID_MY_IMPL_TD:
+ (CLASSID_MY_IMPL_TD = get_dynamic_classid());
+
+ my_impl_transportdata* mytd = (my_impl_transportdata*) new_object
+ (sizeof(my_impl_transportdata), ETCHTYPEB_TRANSPORTDATA, class_id);
+
+ mytd->destroy = destroy_my_impl_transportdata;
+
+ itransport = new_transport_interface_ex (mytd,
+ (etch_transport_control) my_transport_control,
+ (etch_transport_notify) my_transport_notify,
+ (etch_transport_query) my_transport_query,
+ (etch_transport_get_session) my_transport_get_session,
+ (etch_transport_set_session) my_transport_set_session);
+
+ itd = new_transportdata_interface(mytd, impl_transport_data, itransport);
+
+ /* save off i_transportdata destructor */
+ mytd->destroy_transportdata = itd->destroy;
+
+ /* replace i_transportdata destructor with one which will destroy this object */
+ itd->destroy = destroy_my_transportdata;
+
+ mytd->list = new_packetizertest_list();
+
+ /* g_my_transportdata will get set to this interface */
+ mytd->itd = itd;
+
+ return mytd;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * my_impl_sessionpacket (i_sessionpacket implementation)
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * my_impl_sessionpacket
+ * test object implementing i_sessionpacket
+ */
+typedef struct my_impl_sessionpacket
+{
+ 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;
+
+ /* i_sessionpacket interface and methods, plus original destructor
+ * which becomes replaced with a custom destructor to destroy this
+ * object. this is the model for destroying an interface wrapper object
+ * when we do not save and pass around a pointer to the wrapper, but rather
+ * a pointer to the interface. the interface in question, i_sessionpacket
+ * in this case, contains a pointer to the wrapper object, in this case a
+ * my_impl_sessionpacket*. when the interface is instantiated, its original
+ * destructor is saved, and is replaced with a destructor which invokes
+ * the wrapper's destructor. the wrapper destructor must then know to
+ * invoke the interface's original destructor when destroying the interface.
+ */
+ i_sessionpacket* isp; /* owned */
+
+ objdtor destroy_sessionpacket; /* i_sessionpacket original destructor */
+ etch_session_packet session_packet; /* session_packet() */
+
+ etch_what what;
+ etch_who* sender; /* not owned */
+ etch_arraylist* list; /* owned */
+ etch_object* query; /* owned */
+ etch_object* query_result; /* owned */
+ etch_object* control; /* owned */
+ etch_object* value; /* owned */
+ etch_object* eventx; /* owned */
+
+} my_impl_sessionpacket;
+
+
+/**
+ * destroy_my_impl_sessionpacket()
+ * my_impl_sessionpacket destructor
+ */
+int destroy_my_impl_sessionpacket(my_impl_sessionpacket* thisx)
+{
+ if (thisx->refcount > 0 && --thisx->refcount > 0) return -1;
+
+ if (!is_etchobj_static_content(thisx))
+ { /* invoke original i_sessionpacket destructor */
+ if (thisx->isp && thisx->destroy_sessionpacket)
+ thisx->destroy_sessionpacket(thisx->isp);
+
+ if (thisx->list)
+ thisx->list->destroy(thisx->list);
+
+ if (thisx->query)
+ thisx->query->destroy(thisx->query);
+
+ if (thisx->query_result)
+ thisx->query_result->destroy(thisx->query_result);
+
+ if (thisx->control)
+ thisx->control->destroy(thisx->control);
+
+ if (thisx->value)
+ thisx->value->destroy(thisx->value);
+
+ if (thisx->eventx)
+ thisx->eventx->destroy(thisx->eventx);
+ }
+
+ return destroy_objectex((objmask*) thisx);
+}
+
+
+/**
+ * impl_session_packet()
+ * my_impl_sessionpacket::session_packet
+ * @param whofrom caller retains, can be null
+ * @param fbuf caller retains
+ */
+int impl_session_packet (my_impl_sessionpacket* mysp, etch_who* whofrom, etch_flexbuffer* fbuf)
+{
+ etch_nativearray* wrapped_array = NULL;
+ byte* newbuf = NULL;
+ size_t bytecount = 0;
+ CU_ASSERT_FATAL(is_my_impl_sessionpkt(mysp));
+ mysp->what = WHAT_PACKET;
+ mysp->sender = whofrom;
+
+ /* get a new byte vector of the entire packet from the buffer */
+ newbuf = etch_flexbuf_get_all(fbuf, &bytecount);
+
+ /* wrap the packet bytes in an etch_nativearray object */
+ wrapped_array = new_nativearray_from(newbuf,
+ CLASSID_ARRAY_BYTE, sizeof(byte), 1, (int) bytecount, 0, 0);
+
+ /* we want wrapped array to own new packet bytes memory */
+ wrapped_array->is_content_owned = TRUE;
+
+ return arraylist_add(mysp->list, wrapped_array);
+}
+
+
+/**
+ * my_session_control()
+ * my_impl_sessionpacket::isession::session_control
+ */
+int my_session_control (my_impl_sessionpacket* mysp, etch_object* control, etch_object* value)
+{
+ CU_ASSERT_FATAL(is_my_impl_sessionpkt(mysp));
+ mysp->what = SESSION_CONTROL;
+ mysp->control = control;
+ mysp->value = value;
+ return 0;
+}
+
+
+/**
+ * my_session_notify()
+ * my_impl_sessionpacket::isession::session_notify
+ */
+int my_session_notify (my_impl_sessionpacket* mysp, etch_object* evt)
+{
+ CU_ASSERT_FATAL(is_my_impl_sessionpkt(mysp));
+ mysp->what = SESSION_NOTIFY;
+ mysp->eventx = evt;
+ return 0;
+}
+
+
+/**
+ * my_session_query()
+ * my_impl_sessionpacket::isession::session_query
+ */
+objmask* my_session_query (my_impl_sessionpacket* mysp, etch_object* query)
+{
+ etch_object* resultobj = NULL;
+ CU_ASSERT_FATAL(is_my_impl_sessionpkt(mysp));
+ resultobj = mysp->query_result; /* set artificially in test */
+ mysp->what = SESSION_QUERY;
+ mysp->query = query;
+ mysp->query_result = NULL;
+ return (objmask*) resultobj; /* caller owns */
+}
+
+
+/**
+ * new_packetizertest_list()
+ * constructor for a list which owns content memory and where content is etch_object derived.
+ * content will be etch_nativearray objects
+ */
+etch_arraylist* new_packetizertest_list()
+{
+ etch_arraylist* list = new_arraylist(32,0);
+ list->content_type = ETCHARRAYLIST_CONTENT_OBJECT; /* list can call destroy() on list item */
+ list->is_readonly = FALSE;
+ return list;
+}
+
+
+/*
+ * destroy_my_sessionpacket()
+ * i_sessionpacket destructor
+ * this destructor will destroy its parent (my_impl_sessionpacket),
+ * which will in turn destroy this object.
+ */
+int destroy_my_sessionpacket(i_sessionpacket* itp)
+{
+ my_impl_sessionpacket* mytp = NULL;
+ if (NULL == itp) return -1;
+
+ mytp = itp->thisx;
+
+ mytp->destroy(mytp);
+
+ return 0;
+}
+
+
+/**
+ * new_my_impl_sessionpacket()
+ * my_impl_sessionpacket constructor
+ */
+my_impl_sessionpacket* new_my_impl_sessionpacket()
+{
+ i_sessionpacket* isessionpkt = NULL;
+ i_session* isession = NULL;
+ /* this is a model for dynamic class ID assigment */
+ unsigned short class_id = CLASSID_MY_IMPL_SP? CLASSID_MY_IMPL_SP:
+ (CLASSID_MY_IMPL_SP = get_dynamic_classid());
+
+ my_impl_sessionpacket* mysessionpkt = (my_impl_sessionpacket*) new_object
+ (sizeof(my_impl_sessionpacket), ETCHTYPEB_SESSIONPKT, class_id);
+
+ mysessionpkt->destroy = destroy_my_impl_sessionpacket;
+
+ mysessionpkt->list = new_packetizertest_list();
+
+ isession = new_session_interface(mysessionpkt,
+ (etch_session_control) my_session_control,
+ (etch_session_notify) my_session_notify,
+ (etch_session_query) my_session_query);
+
+ isessionpkt = new_sessionpkt_interface(mysessionpkt, impl_session_packet, isession);
+
+ /* save off i_sessionpacket destructor */
+ mysessionpkt->destroy_sessionpacket = isessionpkt->destroy;
+
+ /* replace i_sessionpacket destructor with one which will destroy this object */
+ isessionpkt->destroy = destroy_my_sessionpacket;
+
+ /* g_my_sessionpacket will get set to this interface */
+ mysessionpkt->isp = isessionpkt;
+
+ return mysessionpkt;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - -
+ * support functions
+ * - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * check_packetizer_results()
+ * check array of packetizer result byte arrays against a control byte array.
+ * arrays may be packet payloads, or packets with headers, depending on test.
+ * result arrays are found in the packet handler arraylist, each such list item
+ * being an etch_nativearray object of one dimension, wrapping that result array.
+ * control arrays are passed as an etch_nativearray of two dimensions, created
+ * from a static 2-dimensional array.
+ */
+int check_packetizer_results(i_transportdata* itd, etch_nativearray* expected_array)
+{
+ my_impl_transportdata* mytd = (my_impl_transportdata*) itd->thisx;
+ const int packetcount = mytd->list->count; /* # of result arrays in list */
+ int errors = 0;
+
+ if (NULL == expected_array) /* todo: also check for zero populated count */
+ return packetcount == 0? 0: -1;
+
+ if (packetcount != expected_array->dimension[1])
+ return -1; /* check against count of expected results */
+
+ errors = check_packetized_results(mytd->list, expected_array);
+
+ return errors? -1: 0;
+}
+
+
+/**
+ * check_packetizer_resultx()
+ * check array of packetizer result byte arrays against a control byte array.
+ * arrays may be packet payloads, or packets with headers, depending on test.
+ * result arrays are found in the packet handler arraylist, each such list item
+ * being an etch_nativearray object of one dimension, wrapping that result array.
+ * control arrays are passed as an etch_nativearray of two dimensions, created
+ * from a static 2-dimensional array.
+ */
+int check_packetizer_resultx(i_sessionpacket* isp, etch_nativearray* expected_array)
+{
+ my_impl_sessionpacket* mysp = (my_impl_sessionpacket*) isp->thisx;
+ const int packetcount = mysp->list->count; /* # of result arrays in list */
+ int errors = 0;
+
+ if (NULL == expected_array) /* todo: also check for zero populated count */
+ return packetcount == 0? 0: -1;
+
+ if (packetcount != expected_array->dimension[1])
+ return -1; /* check against count of expected results */
+
+ errors = check_packetized_results(mysp->list, expected_array);
+
+ return errors? -1: 0;
+}
+
+
+/**
+ * check_packetized_results()
+ */
+int check_packetized_results(etch_arraylist* list, etch_nativearray* expected_array)
+{
+ etch_iterator iterator;
+ int result = 0, errors = 0, i = 0;
+ set_iterator(&iterator, list, &list->iterable);
+
+ while(iterator.has_next(&iterator))
+ {
+ /* get result (one-dimension byte array) out of list */
+ etch_nativearray* resultobj = arraylist_get(list, i);
+ byte* packetizedbytes = resultobj->values;
+ size_t packetizedbytecount = resultobj->dimension[0];
+
+ /* get (offset to) this result out of expected results */
+ size_t dim2offset = etch_nativearray_off2(expected_array, i, 0);
+ byte* expected_bytes = (byte*) expected_array->values + dim2offset;
+ size_t expected_bytecount = expected_array->dimension[0];
+
+ result = check_packetized_result(packetizedbytes, packetizedbytecount,
+ expected_bytes, expected_bytecount);
+
+ if (result == -1)
+ errors++;
+
+ i++;
+ iterator.next(&iterator);
+ }
+
+ return errors;
+}
+
+
+/**
+ * check_packetized_result()
+ * check a single packetizer result array against a control array,
+ * each represented as a byte vector. the array can be a packet, or a packet payload,
+ * depending on tested direction of the packetizer call.
+ */
+int check_packetized_result (byte* v1, size_t c1, byte* v2, size_t c2)
+{
+ byte *p = 0, *q = 0;
+ size_t i = 0, errors = 0;
+
+ if (c1 != c2) return FALSE;
+ if (!v1 && !v2) return TRUE;
+ if (!v1 || !v2) return FALSE;
+
+ for(p = v1, q = v2; i < c1; i++, p++, q++)
+ if (*p != *q)
+ errors++;
+
+ return errors? -1: 0;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - -
+ * individual setup and teardown
+ * - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * setup_this_test()
+ */
+int setup_this_test()
+{
+ my_impl_transportdata* mytd_impl = NULL;
+ my_impl_sessionpacket* mysp_impl = NULL;
+
+ /* we instantiate a wrapper x which implements and instantiates i_transportpacket.
+ * the instantiation of i_transportpacket will contain a pointer to x.
+ * our global reference g_my_transportpacket is a pointer to the interface.
+ * the purpose of this excercise is that, in the real binding we can pass
+ * around the interface, whose methods can be then invoked without knowing
+ * anything about the wrapper. when we want to reference the wrapper x,
+ * it is (my_impl_transportpacket) g_my_transportpacket->thisx.
+ */
+ mytd_impl = new_my_impl_transportdata();
+ g_my_transportdata = mytd_impl->itd;
+ CU_ASSERT_FATAL(is_my_impl_transportdata(g_my_transportdata->thisx));
+
+ /* we instantiate a wrapper y which implements and instantiates i_sessionpacket.
+ * the instantiation of i_sessionpacket will contain a pointer to y.
+ * our global reference g_my_sessionpacket is a pointer to the interface.
+ * the purpose of this excercise is that, in the real binding we can pass
+ * around the interface, whose methods can be then invoked without knowing
+ * anything about the wrapper. when we want to reference the wrapper x,
+ * it is (my_impl_sessionpacket*) g_my_sessionpacket->thisx.
+ */
+ mysp_impl = new_my_impl_sessionpacket();
+ g_my_sessionpacket = mysp_impl->isp;
+
+ g_who = new_who(new_int32(THISTEST_WHO_VALUE), TRUE);
+
+ /* finally instantiate the test packetizer */
+ g_my_packetizer = new_packetizer(g_my_transportdata, L"tcp", NULL);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_my_packetizer);
+ g_my_packetizer->set_session(g_my_packetizer, g_my_sessionpacket);
+
+ return 0;
+}
+
+
+/**
+ * teardown_this_test()
+ */
+int teardown_this_test()
+{
+ g_my_packetizer->destroy(g_my_packetizer);
+
+ g_my_sessionpacket->destroy(g_my_sessionpacket); // destroy() is now 0xfeeefeee
+
+ g_my_transportdata->destroy(g_my_transportdata);
+
+ g_who->destroy(g_who);
+
+ if (g_mybuf)
+ g_mybuf->destroy(g_mybuf);
+
+ g_my_packetizer = NULL;
+ g_my_sessionpacket = NULL;
+ g_my_transportdata = NULL;
+ g_mybuf = NULL;
+ g_who = NULL;
+
+ return 0;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - -
+ * tests
+ * - - - - - - - - - - - - - - - - - - - - - -
+ */
+
+/**
+ * test_sessionpacket_constructor()
+ */
+void test_sessionpacket_constructor(void)
+{
+ my_impl_sessionpacket* mysp_impl = new_my_impl_sessionpacket();
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mysp_impl);
+
+ /* the custom interface object destructors are coded to destroy their
+ * implementing objects, so we do that here to verify this functionality.
+ */
+ do
+ { i_sessionpacket* isp = mysp_impl->isp;
+ isp->destroy(isp);
+
+ } while(0);
+
+ 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_transportdata_constructor()
+ */
+void test_transportdata_constructor(void)
+{
+ my_impl_transportdata* mytd_impl = new_my_impl_transportdata();
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mytd_impl);
+
+ /* the custom interface object destructors are coded to destroy their
+ * implementing objects, so we do that here to verify this functionality.
+ */
+ do
+ { i_transportdata* itd = mytd_impl->itd;
+ itd->destroy(itd);
+
+ } while(0);
+
+ 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_packetizer_constructor()
+ */
+void test_packetizer_constructor(void)
+{
+ etch_packetizer* pzr = NULL;
+ i_transportdata* itd = NULL;
+ my_impl_transportdata* mytd_impl = NULL;
+
+ mytd_impl = new_my_impl_transportdata();
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mytd_impl);
+
+ itd = mytd_impl->itd;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(itd);
+
+ /* packetizer does not own i_transportdata* itd */
+ pzr = new_packetizer(itd, L"tcp", NULL);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(pzr);
+
+ pzr->destroy(pzr);
+
+ /* i_transportdata.destroy() will destroy my_impl_transportdata */
+ itd->destroy(itd);
+
+ 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_test_setup()
+ * test that the test setup works with all memory accounted for.
+ * if this test fails, all subsequent tests would also fail.
+ * all subsequent tests should include this skeleton code.
+ */
+void test_test_setup(void)
+{
+ int result = setup_this_test();
+
+ CU_ASSERT_EQUAL_FATAL(result, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_who);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_my_packetizer);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_my_sessionpacket);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_my_transportdata);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_to_source_packet1()
+ * test 1 for packets delivered to packet source
+ */
+void test_to_source_packet1(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ byte* disposable_packet = NULL;
+ #define EXPECTED_HEADERSIZE 8
+ etch_nativearray* expected_result_array = NULL;
+ my_impl_transportdata* mytransport = g_my_transportdata->thisx;
+
+ byte empty_packet[EXPECTED_HEADERSIZE] = { 0,0,0,0, 0,0,0,0, };
+
+ byte expected_result[][EXPECTED_HEADERSIZE] =
+ {
+ {
+ -34,-83,-66,-17, 0,0,0,0,
+ },
+ };
+
+ CU_ASSERT_EQUAL_FATAL(g_my_packetizer->headersize, EXPECTED_HEADERSIZE);
+
+ expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE, sizeof(byte), 2, EXPECTED_HEADERSIZE, 1, 0);
+
+ disposable_packet = etch_malloc(sizeof(empty_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, empty_packet, sizeof(empty_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(empty_packet), 1024, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+
+ result = g_my_packetizer->transport_packet(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result, 0);
+
+ result = check_packetizer_results(g_my_packetizer->transport, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mytransport->what, WHAT_DATA);
+ result = is_equal_who(mytransport->recipient, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ expected_result_array->destroy(expected_result_array);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_to_source_packet2()
+ * test 2 for packets delivered to packet source
+ */
+void test_to_source_packet2(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TTSP2BYTECOUNT 9
+ byte* disposable_packet = NULL;
+ etch_nativearray* expected_result_array = NULL;
+ my_impl_transportdata* mytransport = g_my_transportdata->thisx;
+
+ byte test_packet[TTSP2BYTECOUNT] = { 0,0,0,0, 0,0,0,0, 1 };
+
+ byte expected_result[][TTSP2BYTECOUNT] =
+ { /* --signature--- data-length data */
+ { /* de ad be ef 00 00 00 01 01 */
+ -34,-83,-66,-17, 0, 0, 0, 1, 1
+ },
+ };
+
+ CU_ASSERT_EQUAL_FATAL(g_my_packetizer->headersize, EXPECTED_HEADERSIZE);
+
+ expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE, sizeof(byte), 2, TTSP2BYTECOUNT, 1, 0);
+
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+
+ result = g_my_packetizer->transport_packet(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result, 0);
+
+ result = check_packetizer_results(g_my_packetizer->transport, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mytransport->what, WHAT_DATA);
+ result = is_equal_who(mytransport->recipient, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ expected_result_array->destroy(expected_result_array);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_to_source_packet3()
+ * test 3 for packets delivered to packet source
+ */
+void test_to_source_packet3(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TTSP3BYTECOUNT 10
+ byte* disposable_packet = NULL;
+ etch_nativearray* expected_result_array = NULL;
+ my_impl_transportdata* mytransport = g_my_transportdata->thisx;
+
+ byte test_packet[TTSP3BYTECOUNT] = { 0,0,0,0, 0,0,0,0, 2, 3 };
+
+ byte expected_result[][TTSP3BYTECOUNT] =
+ { /* --signature--- data-length data */
+ { /* de ad be ef 00 00 00 02 02 03 */
+ -34,-83,-66,-17, 0, 0, 0, 2, 2, 3
+ },
+ };
+
+ CU_ASSERT_EQUAL_FATAL(g_my_packetizer->headersize, EXPECTED_HEADERSIZE);
+
+ expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE, sizeof(byte), 2, TTSP3BYTECOUNT, 1, 0);
+
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+
+ result = g_my_packetizer->transport_packet(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result, 0);
+
+ result = check_packetizer_results(g_my_packetizer->transport, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mytransport->what, WHAT_DATA);
+ result = is_equal_who(mytransport->recipient, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ expected_result_array->destroy(expected_result_array);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_to_source_badpacket1()
+ * test 4 for packets delivered to packet source
+ */
+void test_to_source_badpacket1(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TTSP4BYTECOUNT 7
+ byte* disposable_packet = NULL;
+ etch_nativearray* expected_result_array = NULL;
+ my_impl_transportdata* mytransport = g_my_transportdata->thisx;
+
+ byte test_packet[TTSP4BYTECOUNT] = { 0,0,0,0, 0,0,0 }; /* too short */
+
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 256, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+
+ result = g_my_packetizer->transport_packet(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result, -1);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_badpacket1()
+ * test 1 for bad packet data
+ */
+void test_badpacket1(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TBP1COUNT 8
+ byte* disposable_packet = NULL;
+ byte test_packet_1[TBP1COUNT] = { 0,0,0,0, 0,0,0,0 }; /* bad sig */
+ byte test_packet_2[TBP1COUNT] = { 1,2,3,4, 0,0,0,0 }; /* bad sig */
+ byte test_packet_3[TBP1COUNT] = { -34,-83,-66,-17, 0,1,0,0 }; /* bad len */
+
+ /* bad signature 1 */
+ disposable_packet = etch_malloc(sizeof(test_packet_1), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet_1, sizeof(test_packet_1));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet_1), 256, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result, -1);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+
+ /* bad signature 2 */
+ disposable_packet = etch_malloc(sizeof(test_packet_2), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet_2, sizeof(test_packet_2));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet_2), 256, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result, -1);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+
+ /* bad data length (65536) */
+ disposable_packet = etch_malloc(sizeof(test_packet_3), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet_3, sizeof(test_packet_3));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet_3), 256, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result, -1);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_single_single_data()
+ * 3 tests for single packet in a single buffer
+ */
+void test_single_single_data(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TSPSB1BYTECOUNT 8
+ #define TSPSB2BYTECOUNT 9
+ #define TSPSB2RESULTBYTECOUNT 1
+ #define TSPSB3BYTECOUNT 10
+ #define TSPSB3RESULTBYTECOUNT 2
+ byte* disposable_packet = NULL;
+ etch_nativearray* expected_result_2_array = NULL;
+ etch_nativearray* expected_result_3_array = NULL;
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ byte test_packet_1[TSPSB1BYTECOUNT] = { -34,-83,-66,-17, 0,0,0,0, };
+ byte test_packet_2[TSPSB2BYTECOUNT] = { -34,-83,-66,-17, 0,0,0,1, 1, };
+ byte test_packet_3[TSPSB3BYTECOUNT] = { -34,-83,-66,-17, 0,0,0,2, 3,4 };
+
+ byte expected_result_2[][TSPSB2RESULTBYTECOUNT] =
+ {
+ {
+ 1
+ },
+ };
+
+ byte expected_result_3[][TSPSB3RESULTBYTECOUNT] =
+ {
+ {
+ 3, 4
+ },
+ };
+
+ /* test 1 */
+ disposable_packet = etch_malloc(sizeof(test_packet_1), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet_1, sizeof(test_packet_1));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet_1), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet_1));
+
+ result = g_my_packetizer->session_data (g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, NULL);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(mysessionpkt->sender);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+
+ /* test 2 */
+ disposable_packet = etch_malloc(sizeof(test_packet_2), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet_2, sizeof(test_packet_2));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet_2), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet_2));
+
+ result = g_my_packetizer->session_data (g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ expected_result_2_array = new_nativearray_from
+ (&expected_result_2, CLASSID_ARRAY_BYTE, sizeof(byte), 2, TSPSB2RESULTBYTECOUNT, 1, 0);
+
+ result = check_packetizer_resultx (g_my_sessionpacket, expected_result_2_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ expected_result_2_array->destroy(expected_result_2_array);
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ arraylist_clear (mysessionpkt->list, TRUE);
+
+ /* test 3 */
+ disposable_packet = etch_malloc(sizeof(test_packet_3), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet_3, sizeof(test_packet_3));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet_3), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet_3));
+
+ result = g_my_packetizer->session_data (g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ expected_result_3_array = new_nativearray_from
+ (&expected_result_3, CLASSID_ARRAY_BYTE, sizeof(byte), 2, TSPSB3RESULTBYTECOUNT, 1, 0);
+
+ result = check_packetizer_resultx (g_my_sessionpacket, expected_result_3_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ expected_result_3_array->destroy(expected_result_3_array);
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_one_buffer_data_1()
+ * test two packets in a single buffer
+ */
+void test_two_in_one_buffer_data_1(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TWOIN1_1_BYTECOUNT (8 + 8)
+ signed char* disposable_packet;
+
+ signed char test_packet[TWOIN1_1_BYTECOUNT]
+ = { -34,-83,-66,-17, 0,0,0,0,
+ -34,-83,-66,-17, 0,0,0,0,
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, NULL);
+ CU_ASSERT_EQUAL(result, 0);
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(mysessionpkt->sender);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_one_buffer_data_2()
+ * test two packets in a single buffer - 2
+ */
+void test_two_in_one_buffer_data_2(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TWOIN1_2_BYTECOUNT (8 + 1 + 8)
+ #define TWOIN1_2_RESULT_BYTECOUNT 1
+ byte* disposable_packet;
+
+ byte test_packet[TWOIN1_2_BYTECOUNT]
+ = { -34,-83,-66,-17, 0,0,0,1, 1,
+ -34,-83,-66,-17, 0,0,0,0,
+ };
+
+ byte expected_result[][TWOIN1_2_RESULT_BYTECOUNT] =
+ {
+ {
+ 1
+ },
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ etch_nativearray* expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE, sizeof(byte), 2,
+ TWOIN1_2_RESULT_BYTECOUNT, 1, 0);
+
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ expected_result_array->destroy(expected_result_array);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_one_buffer_data_3()
+ * test two packets in a single buffer - 3
+ */
+void test_two_in_one_buffer_data_3(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TWOIN1_3_BYTECOUNT (8 + 8 + 1)
+ #define TWOIN1_3_RESULT_BYTECOUNT 1
+ byte* disposable_packet;
+
+ byte test_packet[TWOIN1_3_BYTECOUNT]
+ = { -34,-83,-66,-17, 0,0,0,0,
+ -34,-83,-66,-17, 0,0,0,1, 2
+ };
+
+ byte expected_result[][TWOIN1_3_RESULT_BYTECOUNT] =
+ {
+ {
+ 2
+ },
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ etch_nativearray* expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE, sizeof(byte), 2,
+ TWOIN1_3_RESULT_BYTECOUNT, 1, 0);
+
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 64, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ expected_result_array->destroy(expected_result_array);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_one_buffer_data_4()
+ * test two packets in a single buffer - 4
+ */
+void test_two_in_one_buffer_data_4(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ signed char* disposable_packet;
+
+ /* byte count for all packets */
+ #define TWOIN1_4_BYTECOUNT (8 + 1 + 8 + 1)
+
+ /* byte count for low order dimension of expected result array ( [2][1] ) */
+ #define TWOIN1_4_RESULT_BYTECOUNT 1
+
+ signed char test_packet[TWOIN1_4_BYTECOUNT]
+ = { -34,-83,-66,-17, 0,0,0,1, 1,
+ -34,-83,-66,-17, 0,0,0,1, 2,
+ };
+
+ signed char expected_result[][TWOIN1_4_RESULT_BYTECOUNT] =
+ {
+ {
+ 1, /* packet 1 data */
+ },
+ {
+ 2, /* packet 2 data */
+ },
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ etch_nativearray* expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE,
+ sizeof(byte), /* size of an array item is 1 */
+ 2, /* count of dimensions [2][1] */
+ 1, /* count of items in low order dimension */
+ 2, /* count of items in secondary dimension */
+ 0); /* 3rd dimension (not applicable) */
+
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ expected_result_array->destroy(expected_result_array);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_one_buffer_data_5()
+ * test two packets in a single buffer - 5
+ */
+void test_two_in_one_buffer_data_5(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ signed char* disposable_packet;
+
+ /* byte count for all packets */
+ #define TWOIN1_5_BYTECOUNT (8 + 2 + 8 + 2)
+
+ /* byte count for low order dimension of expected result array ( [2][2] ) */
+ #define TWOIN1_5_RESULT_BYTECOUNT 2
+
+ signed char test_packet[TWOIN1_5_BYTECOUNT]
+ = { -34,-83,-66,-17, 0,0,0,2, 3, 4,
+ -34,-83,-66,-17, 0,0,0,2, 5, 6,
+ };
+
+ signed char expected_result[][TWOIN1_5_RESULT_BYTECOUNT] =
+ {
+ {
+ 3, 4, /* packet 1 data */
+ },
+ {
+ 5, 6, /* packet 2 data */
+ },
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ etch_nativearray* expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE,
+ sizeof(byte), /* size of an array item is 1 */
+ 2, /* count of dimensions [2][2] */
+ 2, /* count of items in low order dimension */
+ 2, /* count of items in secondary dimension */
+ 0); /* 3rd dimension (not applicable) */
+
+ disposable_packet = etch_malloc(sizeof(test_packet), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, test_packet, sizeof(test_packet));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(test_packet), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(test_packet));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ expected_result_array->destroy(expected_result_array);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_two_buffers_data_1()
+ * test two packets in two buffers with header split across buffers
+ * packets are empty in this test
+ */
+void test_two_in_two_buffers_data_1(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TWOIN2_1_BUF1_BYTECOUNT 6
+ #define TWOIN2_1_BUF2_BYTECOUNT 10
+ etch_flexbuffer* mybuf2=0;
+ byte* disposable_packet=0;
+
+ byte buf1_data[TWOIN2_1_BUF1_BYTECOUNT]
+ = { -34,-83,-66,-17, 0,0, /* packet 1 header (partial) */
+ };
+
+ byte buf2_data[TWOIN2_1_BUF2_BYTECOUNT]
+ = { 0, 0, /* packet 1 header (balance) */
+ -34,-83,-66,-17, 0,0,0,0, /* packet 2 header */
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ /* buffer 1 */
+ disposable_packet = etch_malloc(sizeof(buf1_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf1_data, sizeof(buf1_data));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(buf1_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(buf1_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(mysessionpkt->sender);
+
+ /* buffer 2 */
+ disposable_packet = etch_malloc(sizeof(buf2_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf2_data, sizeof(buf2_data));
+
+ mybuf2 = new_flexbuffer_from(disposable_packet, sizeof(buf2_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mybuf2);
+ CU_ASSERT_EQUAL(mybuf2->datalen, sizeof(buf2_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(mysessionpkt->sender);
+
+ /* done - free memory */
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ mybuf2 ->destroy(mybuf2);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_two_buffers_data_2()
+ * test two packets in two buffers with header split across buffers
+ * packets include bodies in this test
+ */
+void test_two_in_two_buffers_data_2(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TWOIN2_2_BUF1_BYTECOUNT 6
+ #define TWOIN2_2_BUF2_BYTECOUNT (2 + 2 + 8 + 2)
+ /* byte count for low order dimension of expected result array ( [2][2] ) */
+ #define TWOIN2_2_RESULT_BYTECOUNT 2
+ etch_flexbuffer* mybuf2=0;
+ byte* disposable_packet=0;
+
+ byte buf1_data[TWOIN2_2_BUF1_BYTECOUNT]
+ = { -34,-83,-66,-17, 0,0, /* packet 1 header (partial) */
+ };
+
+ byte buf2_data[TWOIN2_2_BUF2_BYTECOUNT]
+ = { 0, 2, /* packet 1 header (balance) */
+ 3, 4, /* packet 1 body */
+ -34,-83,-66,-17, 0,0,0,2, /* packet 2 header */
+ 5, 6, /* packet 2 body */
+ };
+
+ byte expected_result[][TWOIN2_2_RESULT_BYTECOUNT] =
+ {
+ {
+ 3, 4, /* packet 1 body */
+ },
+ {
+ 5, 6, /* packet 2 body */
+ },
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ etch_nativearray* expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE,
+ sizeof(byte), /* size of an array item is 1 */
+ 2, /* count of dimensions [2][2] */
+ 2, /* count of items in low order dimension */
+ 2, /* count of items in secondary dimension */
+ 0 /* 3rd dimension (not applicable) */
+ );
+
+ /* buffer 1 */
+ disposable_packet = etch_malloc(sizeof(buf1_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf1_data, sizeof(buf1_data));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(buf1_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(buf1_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(mysessionpkt->sender);
+
+ /* buffer 2 */
+ disposable_packet = etch_malloc(sizeof(buf2_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf2_data, sizeof(buf2_data));
+
+ mybuf2 = new_flexbuffer_from(disposable_packet, sizeof(buf2_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mybuf2);
+ CU_ASSERT_EQUAL(mybuf2->datalen, sizeof(buf2_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, mybuf2);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ /* done - free memory */
+ expected_result_array->destroy(expected_result_array);
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ mybuf2 ->destroy(mybuf2);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_two_buffers_data_3()
+ * test two packets in two buffers with body split across buffers
+ */
+void test_two_in_two_buffers_data_3(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TWOIN2_3_BUF1_BYTECOUNT (8 + 1) /* header1 + body1 1 of 2 */
+ #define TWOIN2_3_BUF2_BYTECOUNT (1 + 8 + 2) /* body1 2 of 2 + header2 + body2 */
+ /* byte count for low order dimension of expected result array ( [2][2] ) */
+ #define TWOIN2_3_RESULT_BYTECOUNT 2
+ etch_flexbuffer* mybuf2 = NULL;
+ signed char* disposable_packet = NULL;
+
+ signed char buf1_data[TWOIN2_3_BUF1_BYTECOUNT]
+ = { -34,-83,-66,-17, 0, 0, 0, 2, /* packet 1 header (length 2) */
+ 1, /* packet 1 partial body */
+ };
+
+ signed char buf2_data[TWOIN2_3_BUF2_BYTECOUNT]
+ = { 2, /* packet 1 body balance */
+ -34,-83,-66,-17, 0, 0, 0, 2, /* packet 2 header */
+ 3, 4, /* packet 2 body */
+ };
+
+ signed char expected_result[][TWOIN2_3_RESULT_BYTECOUNT] =
+ {
+ {
+ 1, 2, /* packet 1 body */
+ },
+ {
+ 3, 4, /* packet 2 body */
+ },
+ };
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ etch_nativearray* expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE,
+ sizeof(byte), /* size of an array item is 1 */
+ 2, /* count of dimensions [2][2] */
+ 2, /* count of items in low order dimension */
+ 2, /* count of items in secondary dimension */
+ 0 /* 3rd dimension (not applicable) */
+ );
+
+ /* buffer 1 */
+ disposable_packet = etch_malloc(sizeof(buf1_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf1_data, sizeof(buf1_data));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(buf1_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(buf1_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(mysessionpkt->sender);
+
+ /* buffer 2 */
+ disposable_packet = etch_malloc(sizeof(buf2_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf2_data, sizeof(buf2_data));
+
+ mybuf2 = new_flexbuffer_from(disposable_packet, sizeof(buf2_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mybuf2);
+ CU_ASSERT_EQUAL(mybuf2->datalen, sizeof(buf2_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, mybuf2);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+
+ /* done - free memory */
+ expected_result_array->destroy(expected_result_array);
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ mybuf2 ->destroy(mybuf2);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_two_in_two_buffers_data_4()
+ * test two packets in two buffers with body split across buffers
+ */
+void test_two_in_two_buffers_data_4(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ #define TWOIN2_4_BUF1_BYTECOUNT (8 + 2) /* header1 + body1 2 of 3 */
+ #define TWOIN2_4_BUF2_BYTECOUNT (1 + 8 + 3) /* body1 3 of 3 + header2 + body2 */
+ /* byte count for low order dimension of expected result array ( [2][2] ) */
+ #define TWOIN2_4_RESULT_BYTECOUNT 3
+ etch_flexbuffer* mybuf2=0;
+ byte* disposable_packet=0;
+
+ byte buf1_data[TWOIN2_4_BUF1_BYTECOUNT]
+ = { -34,-83,-66,-17, 0, 0, 0, 3, /* packet 1 header (length 2) */
+ 5, 6, /* packet 1 partial body */
+ };
+
+ byte buf2_data[TWOIN2_4_BUF2_BYTECOUNT]
+ = { 7, /* packet 1 body balance */
+ -34,-83,-66,-17, 0, 0, 0, 3, /* packet 2 header */
+ 8, 9, 10 /* packet 2 body */
+ };
+
+ byte expected_result[][TWOIN2_4_RESULT_BYTECOUNT] =
+ {
+ {
+ 5, 6, 7, /* packet 1 body */
+ },
+ {
+ 8, 9, 10, /* packet 2 body */
+ },
+ };
+
+ etch_nativearray* expected_result_array = new_nativearray_from
+ (&expected_result, CLASSID_ARRAY_BYTE,
+ sizeof(byte), /* size of an array item is 1 */
+ 2, /* count of dimensions [2][2] */
+ 3, /* count of items in low order dimension */
+ 2, /* count of items in secondary dimension */
+ 0 /* 3rd dimension (not applicable) */
+ );
+
+ my_impl_sessionpacket* mysessionpkt = g_my_sessionpacket->thisx;
+
+ /* buffer 1 */
+ disposable_packet = etch_malloc(sizeof(buf1_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf1_data, sizeof(buf1_data));
+
+ g_mybuf = new_flexbuffer_from(disposable_packet, sizeof(buf1_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(g_mybuf);
+ CU_ASSERT_EQUAL(g_mybuf->datalen, sizeof(buf1_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, g_mybuf);
+ CU_ASSERT_EQUAL(result,0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(mysessionpkt->sender);
+
+ /* buffer 2 */
+ disposable_packet = etch_malloc(sizeof(buf2_data), ETCHTYPEB_BYTES);
+ memcpy(disposable_packet, buf2_data, sizeof(buf2_data));
+
+ mybuf2 = new_flexbuffer_from(disposable_packet, sizeof(buf2_data), 0, 0);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(mybuf2);
+ CU_ASSERT_EQUAL(mybuf2->datalen, sizeof(buf2_data));
+
+ result = g_my_packetizer->session_data(g_my_packetizer, g_who, mybuf2);
+ CU_ASSERT_EQUAL(result,0);
+
+ result = check_packetizer_resultx(g_my_sessionpacket, expected_result_array);
+ CU_ASSERT_EQUAL(result, 0);
+
+ CU_ASSERT_EQUAL(mysessionpkt->what, WHAT_PACKET);
+ result = is_equal_who(mysessionpkt->sender, g_who);
+ CU_ASSERT_EQUAL(result, TRUE);
+ /* done - free memory */
+ expected_result_array->destroy(expected_result_array);
+ g_mybuf->destroy(g_mybuf); g_mybuf = NULL;
+ mybuf2 ->destroy(mybuf2);
+
+ } while(0);
+
+ teardown_this_test();
+
+ g_bytes_allocated = etch_showmem(0, IS_DEBUG_CONSOLE);
+ CU_ASSERT_EQUAL(g_bytes_allocated, 0);
+ memtable_clear(); /* start fresh for next test */
+}
+
+
+/**
+ * test_session_control
+ * test the session control notification plumbing
+ */
+void test_session_control(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ const int MY_CONTROL_CLASSID = 0x5200, MY_VALUE_CLASSID = 0x5201;
+ etch_object* mycontrolobj = new_etch_object(MY_CONTROL_CLASSID, NULL);
+ etch_object* myvalueobj = new_etch_object(MY_VALUE_CLASSID, NULL);
+
+ /* g_my_sessionpacket is the i_sessionpacket interface
+ * my_impl_sessionpacket is the implementing test class */
+ my_impl_sessionpacket* my_session = g_my_sessionpacket->thisx;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_session);
+ CU_ASSERT_EQUAL(my_session->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(my_session->control);
+ CU_ASSERT_PTR_NULL(my_session->value);
+
+ /* we relinquish memory for mycontrolobj and myvalueobj here.
+ * the session_control terminal destination must destroy them, which here
+ * is handled by our session object destructor when we teardown_this_test() */
+ g_my_packetizer->session_control (g_my_packetizer, mycontrolobj, myvalueobj);
+
+ CU_ASSERT_EQUAL(my_session->what, SESSION_CONTROL);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_session->control);
+ CU_ASSERT_EQUAL(my_session->control->class_id, MY_CONTROL_CLASSID);
+ CU_ASSERT_EQUAL(my_session->value->class_id, MY_VALUE_CLASSID);
+
+ } while(0);
+
+ teardown_this_test();
+
+ 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_session_notify
+ * test the session notify notification plumbing
+ */
+void test_session_notify(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ const int MY_EVENT_CLASSID = 0x5202;
+ etch_object* myeventobj = new_etch_object(MY_EVENT_CLASSID, NULL);
+
+ /* g_my_sessionpacket is the i_sessionpacket interface
+ * my_impl_sessionpacket is the implementing test class */
+ my_impl_sessionpacket* my_session = g_my_sessionpacket->thisx;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_session);
+ CU_ASSERT_EQUAL(my_session->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(my_session->eventx);
+
+ /* we relinquish memory for myeventobj here.
+ * the session_control terminal destination must destroy it, which here
+ * is handled by our session object destructor when we teardown_this_test() */
+ g_my_packetizer->session_notify(g_my_packetizer, myeventobj);
+
+ CU_ASSERT_EQUAL(my_session->what, SESSION_NOTIFY);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_session->eventx);
+ CU_ASSERT_EQUAL(my_session->eventx->class_id, MY_EVENT_CLASSID);
+
+ } while(0);
+
+ teardown_this_test();
+
+ 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_session_query
+ * test the session query notification plumbing
+ */
+void test_session_query(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ const int MY_QUERY_CLASSID = 0x5203, MY_RESULT_CLASSID = 0x5204;
+ etch_object* myqueryobj = new_etch_object(MY_QUERY_CLASSID, NULL);
+ etch_object* myresultobj = new_etch_object(MY_RESULT_CLASSID, NULL);
+ etch_object* queryresult = NULL;
+
+ /* g_my_sessionpacket is the i_sessionpacket interface
+ * my_impl_sessionpacket is the implementing test class */
+ my_impl_sessionpacket* my_session = g_my_sessionpacket->thisx;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_session);
+ CU_ASSERT_EQUAL(my_session->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(my_session->query);
+
+ /* we relinquish myresultobj here. see comments following */
+ my_session->query_result = myresultobj;
+
+ /* we relinquish memory for myqueryobj here and assume queryresult.
+ * the session_control terminal destination must destroy it, which here
+ * is handled by our session object destructor when we teardown_this_test() */
+ queryresult = g_my_packetizer->session_query(g_my_packetizer, myqueryobj);
+
+ CU_ASSERT_EQUAL(my_session->what, SESSION_QUERY);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_session->query);
+ CU_ASSERT_EQUAL(my_session->query->class_id, MY_QUERY_CLASSID);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(queryresult);
+ CU_ASSERT_EQUAL(queryresult->class_id, MY_RESULT_CLASSID);
+ queryresult->destroy(queryresult);
+
+ } while(0);
+
+ teardown_this_test();
+
+ 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_transport_control
+ * test the transport control notification plumbing
+ */
+void test_transport_control(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ const int MY_CONTROL_CLASSID = 0x5200, MY_VALUE_CLASSID = 0x5201;
+ etch_object* mycontrolobj = new_etch_object(MY_CONTROL_CLASSID, NULL);
+ etch_object* myvalueobj = new_etch_object(MY_VALUE_CLASSID, NULL);
+
+ /* g_my_transportdata is the i_transportdata interface
+ * my_impl_transportdata is the implementing test class */
+ my_impl_transportdata* my_transport = g_my_transportdata->thisx;
+ CU_ASSERT_FATAL(is_my_impl_transportdata(my_transport));
+ CU_ASSERT_EQUAL(my_transport->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(my_transport->control);
+ CU_ASSERT_PTR_NULL(my_transport->value);
+
+ /* we relinquish memory for mycontrolobj and myvalueobj here.
+ * the transport_control terminal destination must destroy them, which here
+ * is handled by our transport object destructor when we teardown_this_test() */
+ g_my_packetizer->transport_control(g_my_packetizer, mycontrolobj, myvalueobj);
+
+ CU_ASSERT_EQUAL(my_transport->what, TRANSPORT_CONTROL);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport->control);
+ CU_ASSERT_EQUAL(my_transport->control->class_id, MY_CONTROL_CLASSID);
+ CU_ASSERT_EQUAL(my_transport->value->class_id, MY_VALUE_CLASSID);
+
+ } while(0);
+
+ teardown_this_test();
+
+ 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_transport_notify
+ * test the transport notify notification plumbing
+ */
+void test_transport_notify(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ const int MY_EVENT_CLASSID = 0x5202;
+ etch_object* myeventobj = new_etch_object(MY_EVENT_CLASSID, NULL);
+
+ /* g_my_transportdata is the i_transportdata interface
+ * my_impl_transportdata is the implementing test class */
+ my_impl_transportdata* my_transport = g_my_transportdata->thisx;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport);
+ CU_ASSERT_EQUAL(my_transport->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(my_transport->control);
+ CU_ASSERT_PTR_NULL(my_transport->value);
+
+ /* we relinquish memory for myeventobj here.
+ * the transport_control terminal destination must destroy it, which here
+ * is handled by our transport object destructor when we teardown_this_test() */
+ g_my_packetizer->transport_notify(g_my_packetizer, myeventobj);
+
+ CU_ASSERT_EQUAL(my_transport->what, TRANSPORT_NOTIFY);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport->eventx);
+ CU_ASSERT_EQUAL(my_transport->eventx->class_id, MY_EVENT_CLASSID);
+
+ } while(0);
+
+ teardown_this_test();
+
+ 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_transport_query
+ * test the transport query notification plumbing
+ */
+void test_transport_query(void)
+{
+ setup_this_test();
+
+ do
+ { int result = 0;
+ const int MY_QUERY_CLASSID = 0x5203, MY_RESULT_CLASSID = 0x5204;
+ etch_object* myqueryobj = new_etch_object(MY_QUERY_CLASSID, NULL);
+ etch_object* myresultobj = new_etch_object(MY_RESULT_CLASSID, NULL);
+ etch_object* queryresult = NULL;
+
+ /* g_my_transportdata is the i_transportdata interface
+ * my_impl_transportdata is the implementing test class */
+ my_impl_transportdata* my_transport = g_my_transportdata->thisx;
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport);
+ CU_ASSERT_EQUAL(my_transport->what, WHAT_NONE);
+ CU_ASSERT_PTR_NULL(my_transport->query);
+
+ /* we relinquish myresultobj here. see comments following */
+ my_transport->query_result = myresultobj;
+
+ /* we relinquish memory for myqueryobj here and assume queryresult.
+ * the transport_control terminal destination must destroy it, which here
+ * is handled by our transport object destructor when we teardown_this_test() */
+ queryresult = g_my_packetizer->transport_query(g_my_packetizer, myqueryobj);
+
+ CU_ASSERT_EQUAL(my_transport->what, TRANSPORT_QUERY);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport->query);
+ CU_ASSERT_EQUAL(my_transport->query->class_id, MY_QUERY_CLASSID);
+ CU_ASSERT_PTR_NOT_NULL_FATAL(queryresult);
+ CU_ASSERT_EQUAL(queryresult->class_id, MY_RESULT_CLASSID);
+ queryresult->destroy(queryresult);
+
+ } while(0);
+
+ teardown_this_test();
+
+ 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_packetizer");
+ ps = CU_add_suite("suite_packetizer", init_suite, clean_suite);
+ etch_watch_id = 0;
+
+ CU_add_test(ps, "test sessionpacket ctor/dtor", test_sessionpacket_constructor);
+ CU_add_test(ps, "test transportdata ctor/dtor", test_transportdata_constructor);
+ CU_add_test(ps, "test packetizer ctor/dtor", test_packetizer_constructor);
+ CU_add_test(ps, "test unit test setup/teardown", test_test_setup);
+ CU_add_test(ps, "test packet1 to source", test_to_source_packet1);
+ CU_add_test(ps, "test packet2 to source", test_to_source_packet2);
+ CU_add_test(ps, "test packet3 to source", test_to_source_packet3);
+ CU_add_test(ps, "test bad packet 0", test_to_source_badpacket1);
+ CU_add_test(ps, "test bad packet 1", test_badpacket1);
+
+ CU_add_test(ps, "test 1 packet 1 buffer", test_single_single_data);
+ CU_add_test(ps, "test 2 in 1 buffer 1", test_two_in_one_buffer_data_1);
+ CU_add_test(ps, "test 2 in 1 buffer 2", test_two_in_one_buffer_data_2);
+ CU_add_test(ps, "test 2 in 1 buffer 3", test_two_in_one_buffer_data_3);
+ CU_add_test(ps, "test 2 in 1 buffer 4", test_two_in_one_buffer_data_4);
+ CU_add_test(ps, "test 2 in 1 buffer 5", test_two_in_one_buffer_data_5);
+ CU_add_test(ps, "test 2 in 2 buffers 1", test_two_in_two_buffers_data_1);
+ CU_add_test(ps, "test 2 in 2 buffers 2", test_two_in_two_buffers_data_2);
+ CU_add_test(ps, "test 2 in 2 buffers 3", test_two_in_two_buffers_data_3);
+ CU_add_test(ps, "test 2 in 2 buffers 4", test_two_in_two_buffers_data_4);
+
+ CU_add_test(ps, "test session control", test_session_control);
+ CU_add_test(ps, "test session notify", test_session_notify);
+ CU_add_test(ps, "test session query", test_session_query);
+ CU_add_test(ps, "test transport control", test_transport_control);
+ CU_add_test(ps, "test transport notify", test_transport_notify);
+ CU_add_test(ps, "test transport query", test_transport_query);
+
+ 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();
+}
\ No newline at end of file