| /* $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_messagizer.c | |
| */ | |
| #include "apr_time.h" /* some apr must be included first */ | |
| #include "etch_messagizer.h" | |
| #include "etch_defvalufact.h" | |
| #include <tchar.h> | |
| #include <stdio.h> | |
| #include <conio.h> | |
| #include "cunit.h" | |
| #include "basic.h" | |
| #include "automated.h" | |
| #include "etchthread.h" | |
| #include "etch_global.h" | |
| #include "etchmap.h" | |
| #include "etchlog.h" | |
| #include "etch_syncobj.h" | |
| #include "etchexcp.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 | |
| * - - - - - - - - - - - - - - | |
| */ | |
| typedef struct test_value_factory test_value_factory; | |
| etch_messagizer* g_my_messagizer; | |
| i_transportpacket* g_my_transportpacket; | |
| i_sessionmessage* g_my_sessionmessage; | |
| etch_flexbuffer* g_flexbuffer; | |
| etch_resources* g_my_resources; | |
| vf_idname_map* g_type_map; | |
| class_to_type_map* g_class_to_type_map; | |
| etch_who* g_who; | |
| default_value_factory* g_my_vf; | |
| test_value_factory* g_my_test_vf; | |
| int g_which_valuefactory; | |
| unsigned short CLASSID_MY_VF; | |
| unsigned short CLASSID_MY_VF_VTAB; | |
| unsigned short CLASSID_MY_VF_IMPL; | |
| unsigned short CLASSID_MY_IMPL_TP; | |
| unsigned short CLASSID_MY_IMPL_SM; | |
| #define OBJTYPE_MY_IMPL_TP 0x5170 | |
| #define OBJTYPE_MY_IMPL_SM 0x5171 | |
| #define is_my_impl_tp(x) (x && ((objmask*)x)->obj_type == OBJTYPE_MY_IMPL_TP) | |
| #define is_my_impl_sm(x) (x && ((objmask*)x)->obj_type == OBJTYPE_MY_IMPL_SM) | |
| #define THISTEST_HEADERSIZE 8 | |
| #define TAGDATA_VERSION 3 | |
| #define TYPECODE_EOD_MARK (-127) | |
| #define THISTEST_WHO_VALUE 0x5151 | |
| #define WHICHVF_TESTVF 1 | |
| #define WHICHVF_MYVF 2 | |
| #define FAKEID_TYPE_ADD 1 | |
| #define FAKEID_TYPE_ADD_RESULT 2 | |
| #define FAKEID_FIELD_X 3 | |
| #define FAKEID_FIELD_Y 4 | |
| #define FAKEID_FIELD_RESULT 5 | |
| default_value_factory* get_current_valuefactory() | |
| { | |
| if (g_my_test_vf) return (default_value_factory*) g_my_test_vf; | |
| if (g_my_vf) return g_my_vf; | |
| return NULL; | |
| } | |
| typedef enum etch_what | |
| { WHAT_NONE, | |
| TRANSPORT_PACKET, TRANSPORT_QUERY, TRANSPORT_CONTROL, TRANSPORT_NOTIFY, | |
| SESSION_MESSAGE, 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_transportpacket (i_transportpacket implementation) | |
| * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| */ | |
| /** | |
| * my_impl_transportpacket | |
| * test object implementing i_transportpacket | |
| */ | |
| typedef struct my_impl_transportpacket | |
| { | |
| 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_transportpacket 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_transportpacket | |
| * in this case, contains a pointer to the wrapper object, in this case a | |
| * my_impl_transportpacket*. 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_transportpacket* ixp; /* owned */ | |
| objdtor destroy_transportpacket; /* i_transportpacket original destructor */ | |
| etch_transport_packet transport_packet; /* transport_packet() */ | |
| etch_transport_packet_headersize header_size; /* header_size() */ | |
| i_sessionpacket* session; /* not owned */ | |
| etch_who* recipient; /* not owned */ | |
| etch_what what; | |
| size_t bufcount; | |
| char* buf; /* owned */ | |
| etch_object* query; /* owned */ | |
| etch_object* query_result; /* owned */ | |
| etch_object* control; /* owned */ | |
| etch_object* value; /* owned */ | |
| etch_object* eventx; /* owned */ | |
| } my_impl_transportpacket; | |
| /** | |
| * destroy_my_impl_transportpacket() | |
| * my_impl_transportpacket destructor | |
| */ | |
| int destroy_my_impl_transportpacket(my_impl_transportpacket* thisx) | |
| { | |
| assert(is_my_impl_tp(thisx)); | |
| if (thisx->refcount > 0 && --thisx->refcount > 0) return -1; | |
| if (!is_etchobj_static_content(thisx)) | |
| { /* invoke original i_transportpacket destructor */ | |
| if (thisx->ixp && thisx->destroy_transportpacket) | |
| thisx->destroy_transportpacket(thisx->ixp); | |
| if (thisx->buf) | |
| etch_free(thisx->buf); | |
| 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_packet() | |
| * my_impl_transportpacket::transport_packet | |
| * @param whoto caller retains, can be null | |
| * @param fbuf caller retains | |
| */ | |
| int impl_transport_packet (my_impl_transportpacket* mytp, etch_who* whoto, etch_flexbuffer* fbuf) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_tp(mytp)); | |
| mytp->what = TRANSPORT_PACKET; | |
| mytp->recipient = whoto; | |
| /* retrieve the packet data. don't skip over header (0 is skip bytes) */ | |
| mytp->buf = etch_flexbuf_get_allfrom(fbuf, 0, &mytp->bufcount); | |
| return 0; | |
| } | |
| /** | |
| * my_transport_control() | |
| * my_impl_transportpacket::itransport::transport_control | |
| */ | |
| int my_transport_control (my_impl_transportpacket* mytp, etch_object* control, etch_object* value) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_tp(mytp)); | |
| mytp->what = TRANSPORT_CONTROL; | |
| mytp->control = control; | |
| mytp->value = value; | |
| return 0; | |
| } | |
| /** | |
| * my_transport_notify() | |
| * my_impl_transportpacket::itransport::transport_notify | |
| */ | |
| int my_transport_notify (my_impl_transportpacket* mytp, etch_object* evt) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_tp(mytp)); | |
| mytp->what = TRANSPORT_NOTIFY; | |
| mytp->eventx = evt; | |
| return 0; | |
| } | |
| /** | |
| * my_transport_query() | |
| * my_impl_transportpacket::itransport::transport_query | |
| */ | |
| objmask* my_transport_query (my_impl_transportpacket* mytp, etch_object* query) | |
| { | |
| etch_object* resultobj = NULL; | |
| CU_ASSERT_FATAL(is_my_impl_tp(mytp)); | |
| resultobj = mytp->query_result; /* set artificially in test */ | |
| mytp->what = TRANSPORT_QUERY; | |
| mytp->query = query; | |
| mytp->query_result = NULL; | |
| return (objmask*) resultobj; /* caller owns */ | |
| } | |
| /** | |
| * my_transport_get_session() | |
| * my_impl_transportpacket::itransport::get_session | |
| */ | |
| i_sessionpacket* my_transport_get_session(my_impl_transportpacket* mytp) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_tp(mytp)); | |
| return mytp->session; | |
| } | |
| /** | |
| * my_transport_set_session() | |
| * my_impl_transportpacket::itransport::set_session | |
| */ | |
| void my_transport_set_session(my_impl_transportpacket* mytp, i_sessionpacket* session) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_tp(mytp)); | |
| CU_ASSERT_FATAL(is_etch_sessionpacket(session)); | |
| mytp->session = session; | |
| } | |
| /* | |
| * destroy_my_transportpacket() | |
| * i_transportpacket destructor | |
| * this destructor will destroy its parent (my_impl_transportpacket), | |
| * which will in turn destroy this object. | |
| */ | |
| int destroy_my_transportpacket(i_transportpacket* itp) | |
| { | |
| my_impl_transportpacket* mytp = NULL; | |
| assert(is_etch_transportpkt(itp)); | |
| mytp = itp->thisx; | |
| assert(is_my_impl_tp(mytp)); | |
| mytp->destroy(mytp); | |
| return 0; | |
| } | |
| /** | |
| * new_my_impl_transportpacket() | |
| * my_impl_transportpacket constructor | |
| */ | |
| my_impl_transportpacket* new_my_impl_transportpacket() | |
| { | |
| i_transportpacket* itp = NULL; | |
| i_transport* itransport = NULL; | |
| /* this is a model for dynamic class ID assigment */ | |
| unsigned short class_id = get_dynamic_classid_unique(&CLASSID_MY_IMPL_TP); | |
| my_impl_transportpacket* mytp = (my_impl_transportpacket*) new_object | |
| (sizeof(my_impl_transportpacket), OBJTYPE_MY_IMPL_TP, class_id); | |
| mytp->destroy = destroy_my_impl_transportpacket; | |
| itransport = new_transport_interface_ex(mytp, | |
| (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); | |
| itp = new_transportpkt_interface(mytp, impl_transport_packet, itransport); | |
| /* default header_size() will return this value so no need to override */ | |
| itp->header_size = THISTEST_HEADERSIZE; | |
| /* save off i_transportpacket destructor */ | |
| mytp->destroy_transportpacket = itp->destroy; | |
| /* replace i_transportpacket destructor with one which will destroy this object */ | |
| itp->destroy = destroy_my_transportpacket; | |
| /* g_my_transportpacket will get set to this interface */ | |
| mytp->ixp = itp; | |
| return mytp; | |
| } | |
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| * my_impl_sessionmessage (i_sessionmessage implementation) | |
| * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| */ | |
| /** | |
| * my_impl_sessionmessage | |
| * test object implementing i_sessionmessage | |
| */ | |
| typedef struct my_impl_sessionmessage | |
| { | |
| 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_sessionmessage 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_sessionmessage | |
| * in this case, contains a pointer to the wrapper object, in this case a | |
| * my_impl_sessionmessage*. 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_sessionmessage* ism; /* owned */ | |
| objdtor destroy_sessionmessage; /* i_sessionmessage original destructor */ | |
| etch_session_message session_message; /* session_message() method */ | |
| etch_what what; | |
| etch_who* sender; /* not owned */ | |
| etch_message* msg; /* not owned */ | |
| int is_msg_handled; | |
| etch_object* query; /* owned */ | |
| etch_object* query_result; /* owned */ | |
| etch_object* control; /* owned */ | |
| etch_object* value; /* owned */ | |
| etch_object* eventx; /* owned */ | |
| i_sessionpacket* session; | |
| } my_impl_sessionmessage; | |
| /** | |
| * destroy_my_impl_sessionmessage() | |
| * my_impl_sessionmessage destructor | |
| */ | |
| int destroy_my_impl_sessionmessage(my_impl_sessionmessage* thisx) | |
| { | |
| if (thisx->refcount > 0 && --thisx->refcount > 0) return -1; | |
| if (!is_etchobj_static_content(thisx)) | |
| { /* invoke original i_sessionmessage destructor */ | |
| if (thisx->ism && thisx->destroy_sessionmessage) | |
| thisx->destroy_sessionmessage(thisx->ism); | |
| /* these are objects which would be destroyed in the binding | |
| * by the last method to touch them */ | |
| if (thisx->msg) | |
| thisx->msg->destroy(thisx->msg); | |
| 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_message() | |
| * my_impl_sessionmessage::ism::session_message. | |
| * @param whofrom caller retains, can be null. | |
| * @param msg caller abandons | |
| */ | |
| int impl_session_message (my_impl_sessionmessage* mysm, etch_who* whofrom, etch_message* msg) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_sm(mysm)); | |
| mysm->what = SESSION_MESSAGE; | |
| /* in this emulation we are the session consuming a message. if successful, | |
| * (i.e., the message is handled), the binding will eventually destroy the | |
| * message (the caller relinquishes message memory), and the who object. | |
| * if not successful (message not handled) the caller retains message and | |
| * who memory in order to forward the message and who somewhere else | |
| * (as an unwanted message). so we model that here: if the message is not | |
| * handled (a manual switch in these tests), we do not save references to | |
| * the messaqe and who for cleanup, because the unwanted message, containing | |
| * these objects, will be cleaned up instead. | |
| */ | |
| if (mysm->is_msg_handled) | |
| { | |
| mysm->msg = msg; | |
| mysm->sender = whofrom; | |
| return 0; | |
| } | |
| mysm->msg = NULL; | |
| mysm->sender = NULL; | |
| return -1; | |
| } | |
| /** | |
| * my_session_control() | |
| * my_impl_sessionmessage::ism::isession::session_control | |
| * control and value are always abandoned by caller so mysm must clean them up. | |
| */ | |
| int my_session_control (my_impl_sessionmessage* mysm, etch_object* control, etch_object* value) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_sm(mysm)); | |
| mysm->what = SESSION_CONTROL; | |
| mysm->control = control; | |
| mysm->value = value; | |
| return 0; | |
| } | |
| /** | |
| * my_session_notify() | |
| * my_impl_sessionmessage::ism::isession::session_notify | |
| * evt is always abandoned by caller so mysm must clean it up. | |
| */ | |
| int my_session_notify (my_impl_sessionmessage* mysm, etch_object* evt) | |
| { | |
| CU_ASSERT_FATAL(is_my_impl_sm(mysm)); | |
| mysm->what = SESSION_NOTIFY; | |
| mysm->eventx = evt; | |
| return 0; | |
| } | |
| /** | |
| * my_session_query() | |
| * my_impl_sessionmessage::ism::isession::session_query | |
| * query is always abandoned by caller so mysm must clean it up. | |
| */ | |
| objmask* my_session_query (my_impl_sessionmessage* mysm, etch_object* query) | |
| { | |
| etch_object* resultobj = NULL; | |
| CU_ASSERT_FATAL(is_my_impl_sm(mysm)); | |
| resultobj = mysm->query_result; /* artifically set in test */ | |
| mysm->what = SESSION_QUERY; | |
| mysm->query = query; | |
| mysm->query_result = NULL; | |
| return (objmask*) resultobj; /* caller owns */ | |
| } | |
| /* | |
| * destroy_my_sessionmessage() | |
| * i_sessionmessage destructor | |
| * this destructor will destroy its parent (my_impl_sessionmessage), | |
| * which will in turn destroy this object. | |
| */ | |
| int destroy_my_sessionmessage(i_sessionmessage* ism) | |
| { | |
| my_impl_sessionmessage* mysm = NULL; | |
| if (NULL == ism) return -1; | |
| mysm = ism->thisx; | |
| mysm->destroy(mysm); | |
| return 0; | |
| } | |
| /** | |
| * new_my_impl_sessionmessage() | |
| * my_impl_sessionmessage constructor | |
| */ | |
| my_impl_sessionmessage* new_my_impl_sessionmessage() | |
| { | |
| i_sessionmessage* ism = NULL; | |
| i_session* isession = NULL; | |
| /* this is a model for dynamic class ID assigment */ | |
| unsigned short class_id = CLASSID_MY_IMPL_SM? CLASSID_MY_IMPL_SM: | |
| (CLASSID_MY_IMPL_SM = get_dynamic_classid()); | |
| my_impl_sessionmessage* mysm = (my_impl_sessionmessage*) new_object | |
| (sizeof(my_impl_sessionmessage), OBJTYPE_MY_IMPL_SM, class_id); | |
| mysm->destroy = destroy_my_impl_sessionmessage; | |
| isession = new_session_interface(mysm, | |
| (etch_session_control) my_session_control, | |
| (etch_session_notify) my_session_notify, | |
| (etch_session_query) my_session_query); | |
| ism = new_sessionmsg_interface(mysm, impl_session_message, isession); | |
| /* save off i_sessionmessage destructor */ | |
| mysm->destroy_sessionmessage = ism->destroy; | |
| /* custom destructor will destroy the my_impl_sessionmessage */ | |
| ism->destroy = destroy_my_sessionmessage; | |
| /* g_my_sessionmessage will get set to this interface */ | |
| mysm->ism = ism; | |
| return mysm; | |
| } | |
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| * test value factories | |
| * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| */ | |
| /** | |
| * test_value_factory | |
| * value factory version 1 | |
| * this version uses inherited data coded into the object, as opposed to | |
| * instantiating an impl object to contain inherited data and methods. | |
| */ | |
| typedef struct test_value_factory | |
| { | |
| unsigned int hashkey; | |
| unsigned short obj_type; | |
| unsigned short class_id; | |
| i_value_factory* 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; | |
| /* - - - - - - - - - - - - - | |
| * default value factory | |
| * - - - - - - - - - - - - - | |
| */ | |
| objmask* impl; | |
| class_to_type_map* class_to_type; | |
| vf_idname_map* types; | |
| etch_arraylist* mixins; | |
| unsigned char is_own_types; | |
| unsigned char is_own_class_to_type; | |
| /* - - - - - - - - - - - - - | |
| * test value factory | |
| * - - - - - - - - - - - - - | |
| */ | |
| etch_type* mt_add; | |
| etch_type* mt_add_result; | |
| etch_field* mf_x; | |
| etch_field* mf_y; | |
| etch_field* mf_result; | |
| } test_value_factory; | |
| /** | |
| * destroy_test_value_factory() | |
| * destructor for value factory version 1 | |
| */ | |
| int destroy_test_value_factory(test_value_factory* vf) | |
| { | |
| if (NULL == vf) return -1; | |
| if (vf->refcount > 0) | |
| if (vf->refcount != 1) /* if refcount is 1 */ | |
| { vf->refcount--; /* parent dtor will decrement */ | |
| return -1; | |
| } | |
| if (!is_etchobj_static_content(vf)) | |
| { | |
| destroy_static_type(vf->mt_add); | |
| destroy_static_type(vf->mt_add_result); | |
| destroy_static_field(vf->mf_x); | |
| destroy_static_field(vf->mf_y); | |
| destroy_static_field(vf->mf_result); | |
| } | |
| return destroy_default_value_factory((default_value_factory*) vf); | |
| } | |
| /** | |
| * new_test_valuefactory() | |
| * constructor for value factory version 1 inheriting from default_value_factory | |
| */ | |
| test_value_factory* new_test_valuefactory() | |
| { | |
| etchparentinfo* inheritlist = NULL; | |
| test_value_factory* vf = NULL; | |
| /* establish global dynamic class IDs for the custom vf. | |
| * these global objects are generated by the etch compiler. | |
| */ | |
| const unsigned short class_id_vf = CLASSID_MY_VF? CLASSID_MY_VF: | |
| (CLASSID_MY_VF = get_dynamic_classid()); | |
| const unsigned short class_id_vf_vtab = CLASSID_MY_VF_VTAB? CLASSID_MY_VF_VTAB: | |
| (CLASSID_MY_VF_VTAB = get_dynamic_classid()); | |
| g_type_map = new_vf_types_collection(ETCH_DEFSIZE); | |
| /* since we explicitly instantiate a type map, and since we explicitly destroy | |
| * the test's custom types, we want the type maps destructor to not destroy | |
| * the map content. overriding the map's content clear callback is one way | |
| * to do this. */ | |
| g_type_map->freehook = etch_noop_clear_handler; | |
| g_class_to_type_map = new_class_to_type_map(ETCH_DEFSIZE); | |
| /* instantiate the new value factory. | |
| * this vf does NOT own its type maps since we supply them here. | |
| * however if we wanted to abandon ownership, we could set the | |
| * vf.is_own_types and vf.is_own_class_to_type flags here. | |
| */ | |
| vf = (test_value_factory*) new_default_value_factory_a | |
| (sizeof(test_value_factory), g_type_map, g_class_to_type_map); | |
| vf->destroy = destroy_test_value_factory; | |
| /* ensure parent type keys exist in the (one-based) inheritance list. | |
| * parent class of our custom vf is default_value_factory. | |
| * inheritance list is used by validators and object assignment logic. | |
| */ | |
| inheritlist = get_vtab_inheritance_list((objmask*)vf, 2, 1, CLASSID_MY_VF_VTAB); | |
| inheritlist[1].obj_type = ETCHTYPEB_VALUEFACTORY; | |
| inheritlist[1].class_id = CLASSID_VALUEFACTORY; /* parent class */ | |
| vf->class_id = CLASSID_MY_VF; /* our class */ | |
| /* instantiate the custom vf's instance data and assign it to the vf. | |
| */ | |
| vf->mt_add = new_static_type(L"add"); | |
| vf->mt_add_result = new_static_type(L"add_result"); | |
| vf->mf_x = new_static_field(L"x"); | |
| vf->mf_y = new_static_field(L"y"); | |
| vf->mf_result = new_static_field(L"xresult"); | |
| /* we replace generated ids with 1-byte IDs to make test data buffers easier to construct */ | |
| vf->mt_add->id = FAKEID_TYPE_ADD; | |
| vf->mt_add_result->id = FAKEID_TYPE_ADD_RESULT; | |
| vf->mf_x->id = FAKEID_FIELD_X; | |
| vf->mf_y->id = FAKEID_FIELD_Y; | |
| vf->mf_result->id = FAKEID_FIELD_RESULT; | |
| vf->vtab->add_type(vf, vf->mt_add); | |
| vf->vtab->add_type(vf, vf->mt_add_result); | |
| etchtype_put_validator(vf->mt_add, clone_field(vf->mf_x), | |
| (objmask*) etchvtor_int32_get(0)); | |
| etchtype_put_validator(vf->mt_add, clone_field(vf->mf_y), | |
| (objmask*) etchvtor_int32_get(0)); | |
| etchtype_put_validator(vf->mt_add, clone_field(builtins._mf__message_id), | |
| (objmask*) etchvtor_int64_get(0)); | |
| etchtype_put_validator(vf->mt_add_result, clone_field(vf->mf_result), | |
| (objmask*) etchvtor_int32_get(0)); | |
| etchtype_put_validator(vf->mt_add_result, clone_field(builtins._mf__message_id), | |
| (objmask*) etchvtor_int64_get(0)); | |
| etchtype_put_validator(vf->mt_add_result, clone_field(builtins._mf__in_reply_to), | |
| (objmask*) etchvtor_int64_get(0)); | |
| g_my_test_vf = vf; | |
| return g_my_test_vf; | |
| } | |
| /** | |
| * my_valufactory_impl | |
| * value factory version 2 instance data object | |
| */ | |
| typedef struct my_valufactory_impl | |
| { | |
| 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_type* mt_add; | |
| etch_type* mt_add_result; | |
| etch_field* mf_x; | |
| etch_field* mf_y; | |
| etch_field* mf_result; | |
| } my_valufactory_impl; | |
| /** | |
| * destroy_my_valufactory_impl() | |
| * destructor for inheriting value factory version 2 instance data | |
| */ | |
| int destroy_my_valufactory_impl(my_valufactory_impl* impl) | |
| { | |
| if (NULL == impl) return -1; | |
| if (impl->refcount > 0 && --impl->refcount > 0) return -1; | |
| if (!is_etchobj_static_content(impl)) | |
| { | |
| destroy_static_type(impl->mt_add); | |
| destroy_static_type(impl->mt_add_result); | |
| destroy_static_field(impl->mf_x); | |
| destroy_static_field(impl->mf_y); | |
| destroy_static_field(impl->mf_result); | |
| } | |
| return destroy_objectex((objmask*) impl); | |
| } | |
| /** | |
| * new_my_valufactory_impl() | |
| * constructor for inheriting value factory version 2 instance data | |
| */ | |
| my_valufactory_impl* new_my_valufactory_impl() | |
| { | |
| unsigned short class_id = CLASSID_MY_VF_IMPL? CLASSID_MY_VF_IMPL: | |
| (CLASSID_MY_VF_IMPL = get_dynamic_classid()); | |
| my_valufactory_impl* impl = (my_valufactory_impl*) new_object | |
| (sizeof(my_valufactory_impl), ETCHTYPEB_VALUEFACTIMP, class_id); | |
| impl->destroy = destroy_my_valufactory_impl; | |
| impl->mt_add = new_static_type(L"add"); | |
| impl->mt_add_result = new_static_type(L"add_result"); | |
| impl->mf_x = new_static_field(L"x"); | |
| impl->mf_y = new_static_field(L"y"); | |
| impl->mf_result = new_static_field(L"xresult"); | |
| /* we replace generated ids with 1-byte IDs to make test data buffers easier to construct */ | |
| impl->mt_add->id = FAKEID_TYPE_ADD; | |
| impl->mt_add_result->id = FAKEID_TYPE_ADD_RESULT; | |
| impl->mf_x->id = FAKEID_FIELD_X; | |
| impl->mf_y->id = FAKEID_FIELD_Y; | |
| impl->mf_result->id = FAKEID_FIELD_RESULT; | |
| etchtype_put_validator(impl->mt_add, clone_field(impl->mf_x), | |
| (objmask*) etchvtor_int32_get(0)); | |
| etchtype_put_validator(impl->mt_add, clone_field(impl->mf_y), | |
| (objmask*) etchvtor_int32_get(0)); | |
| etchtype_put_validator(impl->mt_add, clone_field(builtins._mf__message_id), | |
| (objmask*) etchvtor_int64_get(0)); | |
| etchtype_put_validator(impl->mt_add_result, clone_field(impl->mf_result), | |
| (objmask*) etchvtor_int32_get(0)); | |
| etchtype_put_validator(impl->mt_add_result, clone_field(builtins._mf__message_id), | |
| (objmask*) etchvtor_int64_get(0)); | |
| etchtype_put_validator(impl->mt_add_result, clone_field(builtins._mf__in_reply_to), | |
| (objmask*) etchvtor_int64_get(0)); | |
| return impl; | |
| } | |
| /** | |
| * new_bogus_valuefactory() | |
| * constructor for value factory version 2 inheriting from default_value_factory | |
| */ | |
| default_value_factory* new_bogus_valuefactory() | |
| { | |
| etchparentinfo* inheritlist = NULL; | |
| my_valufactory_impl* impl = NULL; | |
| /* establish global dynamic class IDs for the custom vf. | |
| * these global objects are generated by the etch compiler. | |
| */ | |
| const unsigned short class_id_vf = CLASSID_MY_VF? CLASSID_MY_VF: | |
| (CLASSID_MY_VF = get_dynamic_classid()); | |
| const unsigned short class_id_vf_vtab = CLASSID_MY_VF_VTAB? CLASSID_MY_VF_VTAB: | |
| (CLASSID_MY_VF_VTAB = get_dynamic_classid()); | |
| g_type_map = new_vf_types_collection(ETCH_DEFSIZE); | |
| /* since we explicitly instantiate a type map, and since we explicitly destroy | |
| * the test's custom types, we want the type maps destructor to not destroy | |
| * the map content. overriding the map's content clear callback is one way | |
| * to do this. */ | |
| g_type_map->freehook = etch_noop_clear_handler; | |
| g_class_to_type_map = new_class_to_type_map(ETCH_DEFSIZE); | |
| /* instantiate the new value factory. | |
| * this vf does NOT own its type maps since we supply them here. | |
| * however if we wanted to abandon ownership, we could clear the | |
| * vf.is_own_types and vf.is_own_class_to_type flags here. | |
| */ | |
| g_my_vf = new_default_value_factory(g_type_map, g_class_to_type_map); | |
| /* ensure parent type keys exist in the (one-based) inheritance list. | |
| * parent class of our custom vf is default_value_factory. | |
| * inheritance list is used by validators and object assignment logic. | |
| */ | |
| inheritlist = get_vtab_inheritance_list((objmask*)g_my_vf, 2, 1, CLASSID_MY_VF_VTAB); | |
| inheritlist[1].obj_type = ETCHTYPEB_VALUEFACTORY; | |
| inheritlist[1].class_id = CLASSID_VALUEFACTORY; /* parent class */ | |
| g_my_vf->class_id = CLASSID_MY_VF; /* our class */ | |
| /* instantiate the custom vf's instance data and assign it to the vf. | |
| * the impl comprises all data specific to the inheriting class, including | |
| * data and methods if any. the default value factory destructor will call | |
| * the destructor on the vf's impl object. | |
| */ | |
| impl = new_my_valufactory_impl(); | |
| g_my_vf->impl = (objmask*) impl; | |
| g_my_vf->vtab->add_type(g_my_vf, impl->mt_add); | |
| g_my_vf->vtab->add_type(g_my_vf, impl->mt_add_result); | |
| return g_my_vf; | |
| } | |
| /** | |
| * get_vftype() | |
| * return a type depending on which version of value factory is instantiated | |
| */ | |
| etch_type* get_vftype(const int typeid) | |
| { | |
| etch_type* type = NULL; | |
| if (g_my_vf) | |
| { | |
| my_valufactory_impl* impl = (my_valufactory_impl*) g_my_vf->impl; | |
| if (typeid == impl->mt_add->id) | |
| type = impl->mt_add; | |
| else | |
| if (typeid == impl->mt_add_result->id) | |
| type = impl->mt_add_result; | |
| } | |
| else | |
| if (g_my_test_vf) | |
| { | |
| if (typeid == g_my_test_vf->mt_add->id) | |
| type = g_my_test_vf->mt_add; | |
| else | |
| if (typeid == g_my_test_vf->mt_add_result->id) | |
| type = g_my_test_vf->mt_add_result; | |
| } | |
| return type; | |
| } | |
| /* - - - - - - - - - - - - - - - - - | |
| * test messagizer | |
| * - - - - - - - - - - - - - - - - - | |
| */ | |
| /** | |
| * new_bogus_messagizer() | |
| */ | |
| etch_messagizer* new_bogus_messagizer(i_transportpacket* transport) | |
| { | |
| g_my_messagizer = new_messagizer(transport, L"foo:?Messagizer.format=binary", g_my_resources); | |
| return g_my_messagizer; | |
| } | |
| /* - - - - - - - - - - - - - - - - - - - - - | |
| * individual test data setup and teardown | |
| * - - - - - - - - - - - - - - - - - - - - - | |
| */ | |
| /** | |
| * setup_this_test() | |
| */ | |
| int setup_this_test(const int which_valuefactory) | |
| { | |
| my_impl_transportpacket* mytp_impl = NULL; | |
| my_impl_sessionmessage* mysm_impl = NULL; | |
| default_value_factory* thisvf = NULL; | |
| g_which_valuefactory = which_valuefactory; | |
| /* two versions of value factory using different inheritance models */ | |
| if (which_valuefactory == WHICHVF_TESTVF) /* vf version 1 inline inheritance */ | |
| { thisvf = (default_value_factory*) new_test_valuefactory(); | |
| set_etchobj_static_all(g_my_test_vf); /* so resources will not destroy */ | |
| } | |
| else | |
| { thisvf = new_bogus_valuefactory(); /* vf version 2 impl object inheritance */ | |
| set_etchobj_static_all(g_my_vf); /* so resources will not destroy */ | |
| } | |
| g_my_resources = new_etch_resources(ETCH_DEFSIZE); | |
| etch_resources_add(g_my_resources, ETCH_RESXKEY_MSGIZER_VALUFACT, (objmask*) thisvf); | |
| /* 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. | |
| */ | |
| mytp_impl = new_my_impl_transportpacket(); | |
| g_my_transportpacket = mytp_impl->ixp; | |
| /* we instantiate a wrapper y which implements and instantiates i_sessionmessage. | |
| * the instantiation of i_sessionmessage will contain a pointer to y. | |
| * our global reference g_my_sessionmessage 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_sessionmessage*) g_my_sessionmessage->thisx. | |
| */ | |
| mysm_impl = new_my_impl_sessionmessage(); | |
| g_my_sessionmessage = mysm_impl->ism; | |
| g_who = new_who(new_int32(THISTEST_WHO_VALUE), TRUE); | |
| /* finally instantiate the test messagizer */ | |
| new_bogus_messagizer(g_my_transportpacket); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(g_my_messagizer); | |
| etch_msgizer_set_session(g_my_messagizer, g_my_sessionmessage); | |
| return 0; | |
| } | |
| /** | |
| * teardown_this_test() | |
| */ | |
| int teardown_this_test() | |
| { | |
| g_my_messagizer->destroy(g_my_messagizer); | |
| g_my_transportpacket->destroy(g_my_transportpacket); | |
| g_my_sessionmessage->destroy(g_my_sessionmessage); | |
| g_my_resources->destroy(g_my_resources); | |
| if (g_my_vf) | |
| { clear_etchobj_static_all(g_my_vf); | |
| g_my_vf->destroy(g_my_vf); | |
| } | |
| else /* can only instantiate one or the other */ | |
| if (g_my_test_vf) | |
| { clear_etchobj_static_all(g_my_test_vf); | |
| g_my_test_vf->destroy(g_my_test_vf); | |
| } | |
| g_who->destroy(g_who); | |
| g_type_map->destroy(g_type_map); // ************************************************ | |
| g_class_to_type_map->destroy(g_class_to_type_map); | |
| if (g_flexbuffer) | |
| g_flexbuffer->destroy(g_flexbuffer); | |
| g_my_transportpacket = NULL; | |
| g_my_sessionmessage = NULL; | |
| g_class_to_type_map = NULL; | |
| g_my_messagizer = NULL; | |
| g_my_resources = NULL; | |
| g_flexbuffer = NULL; | |
| g_my_test_vf = NULL; | |
| g_type_map = NULL; | |
| g_my_vf = NULL; | |
| g_who = NULL; | |
| etchvf_free_builtins(); | |
| return 0; | |
| } | |
| /* - - - - - - - - - - - - - - | |
| * unit tests | |
| * - - - - - - - - - - - - - - | |
| */ | |
| /** | |
| * test_transportpacket_constructor() | |
| */ | |
| void test_transportpacket_constructor(void) | |
| { | |
| my_impl_transportpacket* mytp_impl = new_my_impl_transportpacket(); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(mytp_impl); | |
| /* the custom interface object destructors are coded to destroy their | |
| * implementing objects, so we do that here to verify this functionality. | |
| */ | |
| do | |
| { i_transportpacket* itp = mytp_impl->ixp; | |
| itp->destroy(itp); | |
| } 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_sessionmessage_constructor() | |
| */ | |
| void test_sessionmessage_constructor(void) | |
| { | |
| my_impl_sessionmessage* mysm_impl = new_my_impl_sessionmessage(); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(mysm_impl); | |
| /* the custom interface object destructors are coded to destroy their | |
| * implementing objects, so we do that here to verify this functionality. | |
| */ | |
| do | |
| { i_sessionmessage* ism = mysm_impl->ism; | |
| ism->destroy(ism); | |
| } 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_messagizer_constructor() | |
| */ | |
| void test_messagizer_constructor(void) | |
| { | |
| etch_messagizer* mzr = NULL; | |
| i_transportpacket* itp = NULL; | |
| etch_resources* resxmap = NULL; | |
| default_value_factory* vf = NULL; | |
| my_impl_transportpacket* mytp_impl = NULL; | |
| vf = new_default_value_factory(NULL, NULL); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(vf); | |
| set_etchobj_static_all(vf); /* so resources will not destroy */ | |
| resxmap = new_etch_resources(ETCH_DEFSIZE); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(resxmap); | |
| etch_resources_add(resxmap, ETCH_RESXKEY_MSGIZER_VALUFACT, (objmask*) vf); | |
| mytp_impl = new_my_impl_transportpacket(); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(mytp_impl); | |
| itp = mytp_impl->ixp; | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(itp); | |
| /* messagizer does not own i_transportpacket* itp */ | |
| mzr = new_messagizer(itp, L"foo:?Messagizer.format=binary", resxmap); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(mzr); | |
| mzr->destroy(mzr); | |
| /* i_transportpacket.destroy() will destroy my_impl_transportpacket */ | |
| itp->destroy(itp); | |
| resxmap->destroy(resxmap); | |
| clear_etchobj_static_all(vf); /* so we can destroy it now */ | |
| vf->destroy(vf); | |
| etchvf_free_builtins(); | |
| 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_testsetup_teardown_a | |
| */ | |
| void test_testsetup_teardown_a(void) | |
| { | |
| setup_this_test(WHICHVF_TESTVF); | |
| 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_testsetup_teardown_b | |
| */ | |
| void test_testsetup_teardown_b(void) | |
| { | |
| setup_this_test(WHICHVF_MYVF); | |
| 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_packet_1 | |
| * mimics the transport messagizing a packet and delivering the message to the session | |
| */ | |
| void test_packet_1(void) | |
| { | |
| setup_this_test(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| etch_type* msgtype = NULL; | |
| etch_flexbuffer* fbuf = NULL; | |
| const int THISTEST_BUFSIZE = 4; | |
| char* buf = etch_malloc(THISTEST_BUFSIZE, ETCHTYPEB_BYTES); | |
| /* g_my_sessionmessage is the i_sessionmessage interface | |
| * my_impl_sessionmessage is the implementing test class */ | |
| my_impl_sessionmessage* my_session = g_my_sessionmessage->thisx; | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_session); | |
| /* load up the packet buffer with test data */ | |
| buf[0] = TAGDATA_VERSION; buf[1] = FAKEID_TYPE_ADD; buf[2] = 0; buf[3] = TYPECODE_EOD_MARK; | |
| g_flexbuffer = new_flexbuffer_from(buf, THISTEST_BUFSIZE, THISTEST_BUFSIZE, 0); | |
| my_session->is_msg_handled = TRUE; | |
| /* messagize the packet and deliver the message to the session */ | |
| result = g_my_messagizer->session_packet (g_my_messagizer, g_who, g_flexbuffer); | |
| CU_ASSERT_EQUAL(result, 0); | |
| if (0 != result) break; | |
| CU_ASSERT_EQUAL(my_session->what, SESSION_MESSAGE); | |
| result = is_equal_who(my_session->sender, g_who); | |
| CU_ASSERT_EQUAL(result, TRUE); | |
| CU_ASSERT_EQUAL(message_size(my_session->msg), 0); | |
| CU_ASSERT_PTR_NULL(my_session->eventx); | |
| /* assert that message type is "add" (since we buffered FAKEID_TYPE_ADD above) */ | |
| msgtype = message_type(my_session->msg); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(msgtype); | |
| CU_ASSERT_EQUAL(msgtype->id, FAKEID_TYPE_ADD); | |
| } 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_packet_2 | |
| * mimics the transport messagizing a packet and delivering the message to the session | |
| * which rejects the message and forwards the message as rejected. | |
| */ | |
| void test_packet_2(void) | |
| { | |
| setup_this_test(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| etch_type* msgtype = NULL; | |
| etch_flexbuffer* fbuf = NULL; | |
| const int THISTEST_BUFSIZE = 4; | |
| etch_message* thismessage = NULL; | |
| etch_unwanted_message* uwmsg = NULL; | |
| char* buf = etch_malloc(THISTEST_BUFSIZE, ETCHTYPEB_BYTES); | |
| /* g_my_sessionmessage is the i_sessionmessage interface | |
| * my_impl_sessionmessage is the implementing test class */ | |
| my_impl_sessionmessage* my_session = g_my_sessionmessage->thisx; | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_session); | |
| /* load up the packet buffer with test data */ | |
| buf[0] = TAGDATA_VERSION; buf[1] = FAKEID_TYPE_ADD; buf[2] = 0; buf[3] = TYPECODE_EOD_MARK; | |
| g_flexbuffer = new_flexbuffer_from(buf, THISTEST_BUFSIZE, THISTEST_BUFSIZE, 0); | |
| /* for the purposes of this test we manually specify that the message was not handled. | |
| * when this is the case, the message and who will be wrapped up in an "unwanted message" | |
| * which is forwarded to the session as an event. when this is the case, memory for the | |
| * message and who is not cleaned up by the session in the normal manner, but is instead | |
| * owned by the unwanted message, and destroyed with that object. | |
| */ | |
| my_session->is_msg_handled = FALSE; | |
| /* messagize the packet and deliver the message to the session */ | |
| result = g_my_messagizer->session_packet (g_my_messagizer, g_who, g_flexbuffer); | |
| CU_ASSERT_EQUAL(result, 0); | |
| if (0 != result) break; | |
| CU_ASSERT_EQUAL(my_session->what, SESSION_NOTIFY); | |
| CU_ASSERT_EQUAL(message_size(my_session->msg), 0); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_session->eventx); | |
| uwmsg = (etch_unwanted_message*) my_session->eventx; | |
| CU_ASSERT_EQUAL_FATAL(uwmsg->class_id, CLASSID_EVENT_UNWANTMSG); | |
| /* find the message and who in the "unwanted message" wrapper */ | |
| result = is_equal_who(uwmsg->whofrom, g_who); | |
| CU_ASSERT_EQUAL(result, TRUE); | |
| thismessage = uwmsg->message; | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(thismessage); | |
| /* assert that message type is "add" (since we buffered FAKEID_TYPE_ADD above) */ | |
| msgtype = message_type(thismessage); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(msgtype); | |
| CU_ASSERT_EQUAL(msgtype->id, FAKEID_TYPE_ADD); | |
| } 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_packet_3 | |
| * mimics the transport messagizing a packet and delivering the message to the session | |
| */ | |
| void test_packet_3(void) | |
| { | |
| setup_this_test(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| etch_type* msgtype = NULL; | |
| etch_flexbuffer* fbuf = NULL; | |
| const int THISTEST_BUFSIZE = 4; | |
| etch_message* thismessage = NULL; | |
| etch_unwanted_message* uwmsg = NULL; | |
| char* buf = etch_malloc(THISTEST_BUFSIZE, ETCHTYPEB_BYTES); | |
| /* g_my_sessionmessage is the i_sessionmessage interface | |
| * my_impl_sessionmessage is the implementing test class */ | |
| my_impl_sessionmessage* my_session = g_my_sessionmessage->thisx; | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_session); | |
| /* load up the packet buffer with test data */ | |
| buf[0] = TAGDATA_VERSION; | |
| buf[1] = FAKEID_TYPE_ADD_RESULT; | |
| buf[2] = 0; | |
| buf[3] = TYPECODE_EOD_MARK; | |
| g_flexbuffer = new_flexbuffer_from(buf, THISTEST_BUFSIZE, THISTEST_BUFSIZE, 0); | |
| /* for the purposes of this test we manually specify that the message was handled */ | |
| my_session->is_msg_handled = TRUE; | |
| /* messagize the packet and deliver the message to the session */ | |
| result = g_my_messagizer->session_packet (g_my_messagizer, g_who, g_flexbuffer); | |
| CU_ASSERT_EQUAL(result, 0); | |
| if (0 != result) break; | |
| CU_ASSERT_EQUAL(my_session->what, SESSION_MESSAGE); | |
| CU_ASSERT_EQUAL(message_size(my_session->msg), 0); | |
| /* assert that message type is "add_result" (since we buffered FAKEID_TYPE_ADD_RESULT above) */ | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_session->msg); | |
| msgtype = message_type(my_session->msg); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(msgtype); | |
| CU_ASSERT_EQUAL(msgtype->id, FAKEID_TYPE_ADD_RESULT); | |
| } 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_message_1 | |
| * mimics the session buffering a message and delivering it to the transport | |
| */ | |
| void test_message_1(void) | |
| { | |
| setup_this_test(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| etch_type* msgtype = NULL; | |
| etch_value_factory* vf = NULL; | |
| const int EXPECTED_BUFSIZE = 4; | |
| etch_message* thismessage = NULL; | |
| /* g_my_transportpacket is the i_transportpacket interface | |
| * my_impl_transportpacket is the implementing test class */ | |
| my_impl_transportpacket* my_transport = g_my_transportpacket->thisx; | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport); | |
| vf = (etch_value_factory*) get_current_valuefactory(); | |
| msgtype = get_vftype(FAKEID_TYPE_ADD); | |
| g_my_transportpacket->header_size = 0; /* test no header */ | |
| thismessage = new_message(msgtype, ETCH_DEFSIZE, vf); | |
| /* buffer up the message and deliver to transport */ | |
| result = g_my_messagizer->transport_message (g_my_messagizer, g_who, thismessage); | |
| CU_ASSERT_EQUAL(result, 0); | |
| if (0 != result) break; | |
| CU_ASSERT_EQUAL(my_transport->what, TRANSPORT_PACKET); | |
| result = is_equal_who(my_transport->recipient, g_who); | |
| CU_ASSERT_EQUAL(result, TRUE); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport->buf); | |
| CU_ASSERT_EQUAL(my_transport->bufcount, EXPECTED_BUFSIZE); | |
| /* check that packet buffer contains expected serialized message */ | |
| CU_ASSERT_EQUAL(my_transport->buf[0], TAGDATA_VERSION); | |
| CU_ASSERT_EQUAL(my_transport->buf[1], FAKEID_TYPE_ADD); | |
| CU_ASSERT_EQUAL(my_transport->buf[2], 0); | |
| CU_ASSERT_EQUAL(my_transport->buf[3], TYPECODE_EOD_MARK); | |
| } 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_message_2 | |
| * mimics the session buffering a message and delivering it to the transport | |
| */ | |
| void test_message_2(void) | |
| { | |
| setup_this_test(WHICHVF_TESTVF); | |
| do | |
| { int result = 0, i = 0, errs = 0; | |
| etch_type* msgtype = NULL; | |
| etch_value_factory* vf = NULL; | |
| etch_message* thismessage = NULL; | |
| const int TEST_HEADER_SIZE = 8, EXPECTED_BUFSIZE = 4 + TEST_HEADER_SIZE; | |
| /* g_my_transportpacket is the i_transportpacket interface | |
| * my_impl_transportpacket is the implementing test class */ | |
| my_impl_transportpacket* my_transport = g_my_transportpacket->thisx; | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport); | |
| vf = (etch_value_factory*) get_current_valuefactory(); | |
| msgtype = get_vftype(FAKEID_TYPE_ADD_RESULT); | |
| g_my_transportpacket->header_size = TEST_HEADER_SIZE; /* test with 8-byte header */ | |
| thismessage = new_message(msgtype, ETCH_DEFSIZE, vf); | |
| /* buffer up the message and deliver to transport */ | |
| result = g_my_messagizer->transport_message(g_my_messagizer, g_who, thismessage); | |
| CU_ASSERT_EQUAL(result, 0); | |
| if (0 != result) break; | |
| CU_ASSERT_EQUAL(my_transport->what, TRANSPORT_PACKET); | |
| result = is_equal_who(my_transport->recipient, g_who); | |
| CU_ASSERT_EQUAL(result, TRUE); | |
| CU_ASSERT_PTR_NOT_NULL_FATAL(my_transport->buf); | |
| CU_ASSERT_EQUAL(my_transport->bufcount, EXPECTED_BUFSIZE); | |
| /* check that packet buffer contains expected serialized message */ | |
| for(; i < TEST_HEADER_SIZE; i++) if (my_transport->buf[i]) errs++; | |
| CU_ASSERT_EQUAL(errs, 0); | |
| CU_ASSERT_EQUAL(my_transport->buf[8], TAGDATA_VERSION); | |
| CU_ASSERT_EQUAL(my_transport->buf[9], FAKEID_TYPE_ADD_RESULT); | |
| CU_ASSERT_EQUAL(my_transport->buf[10],0); | |
| CU_ASSERT_EQUAL(my_transport->buf[11],TYPECODE_EOD_MARK); | |
| } 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_control | |
| * test the session control notification plumbing | |
| */ | |
| void test_session_control(void) | |
| { | |
| setup_this_test(WHICHVF_TESTVF); | |
| 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_sessionmessage is the i_sessionmessage interface | |
| * my_impl_sessionmessage is the implementing test class */ | |
| my_impl_sessionmessage* my_session = g_my_sessionmessage->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_messagizer->session_control(g_my_messagizer, 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(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| const int MY_EVENT_CLASSID = 0x5202; | |
| etch_object* myeventobj = new_etch_object(MY_EVENT_CLASSID, NULL); | |
| /* g_my_sessionmessage is the i_sessionmessage interface | |
| * my_impl_sessionmessage is the implementing test class */ | |
| my_impl_sessionmessage* my_session = g_my_sessionmessage->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_messagizer->session_notify(g_my_messagizer, 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(WHICHVF_TESTVF); | |
| 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_sessionmessage is the i_sessionmessage interface | |
| * my_impl_sessionmessage is the implementing test class */ | |
| my_impl_sessionmessage* my_session = g_my_sessionmessage->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_messagizer->session_query (g_my_messagizer, 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(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| my_impl_transportpacket* my_transport = NULL; | |
| 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_transportpacket is the i_transportpacket interface | |
| * my_impl_transportpacket is the implementing test class | |
| */ | |
| g_my_messagizer->transport = g_my_transportpacket; | |
| my_transport = g_my_transportpacket->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 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_messagizer->transport_control (g_my_messagizer, 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(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| my_impl_transportpacket* my_transport = NULL; | |
| const int MY_EVENT_CLASSID = 0x5202; | |
| etch_object* myeventobj = new_etch_object(MY_EVENT_CLASSID, NULL); | |
| /* g_my_transportpacket is the i_transportpacket interface | |
| * my_impl_transportpacket is the implementing test class | |
| */ | |
| g_my_messagizer->transport = g_my_transportpacket; | |
| my_transport = g_my_transportpacket->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_messagizer->transport_notify (g_my_messagizer, 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(WHICHVF_TESTVF); | |
| do | |
| { int result = 0; | |
| my_impl_transportpacket* my_transport = NULL; | |
| 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_transportpacket is the i_transportpacket interface | |
| * my_impl_transportpacket is the implementing test class | |
| */ | |
| g_my_messagizer->transport = g_my_transportpacket; | |
| my_transport = g_my_transportpacket->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 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_messagizer->transport_query (g_my_messagizer, 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 pSuite = NULL; | |
| g_is_automated_test = argc > 1 && 0 != wcscmp(argv[1], L"-a"); | |
| if (CUE_SUCCESS != CU_initialize_registry()) return 0; | |
| pSuite = CU_add_suite("suite messagizer", init_suite, clean_suite); | |
| CU_set_output_filename("../test_messagizer"); | |
| etch_watch_id = 0; | |
| CU_add_test(pSuite, "test transportpacket impl constructor", test_transportpacket_constructor); | |
| CU_add_test(pSuite, "test sessionmessage impl constructor", test_sessionmessage_constructor); | |
| CU_add_test(pSuite, "test messagizer constructor", test_messagizer_constructor); | |
| CU_add_test(pSuite, "test test setup and teardown v1", test_testsetup_teardown_a); | |
| CU_add_test(pSuite, "test test setup and teardown v2", test_testsetup_teardown_b); | |
| CU_add_test(pSuite, "test packet 1", test_packet_1); | |
| CU_add_test(pSuite, "test packet 2", test_packet_2); | |
| CU_add_test(pSuite, "test packet 3", test_packet_2); | |
| CU_add_test(pSuite, "test message 1", test_message_1); | |
| CU_add_test(pSuite, "test message 2", test_message_2); | |
| CU_add_test(pSuite, "test session control",test_session_control); | |
| CU_add_test(pSuite, "test session notify", test_session_notify); | |
| CU_add_test(pSuite, "test session query", test_session_query); | |
| CU_add_test(pSuite, "test transport control",test_transport_control); | |
| CU_add_test(pSuite, "test transport notify", test_transport_notify); | |
| CU_add_test(pSuite, "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(); printf("\n"); } | |
| CU_cleanup_registry(); | |
| return CU_get_error(); | |
| } |