2 ==================================================================================
3 Copyright (c) 2019 Nokia
4 Copyright (c) 2018-2019 AT&T Intellectual Property.
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
21 Mnemonic: test_nng_em.c
22 Abstract: A nano/NNG message emulator for testing without needing to
23 actually have nanomsg, nng, or external processes.
24 We also emulate the epoll_wait() function for controlled
27 This module must be directly included to be used.
28 Date: 11 February 2019
29 Author: E. Scott Daniels
32 // ---------------------- emulated nng functions ---------------------------
38 static int em_send_failures = 0; // test programme can set this to emulate eagain send failures
40 // ----------- epoll emulation ---------------------------------------------
42 // CAUTION: sys/epoll.h must be included before this define and function will properly compile.
43 #define epoll_wait em_wait
45 Every other call returns 1 ready; alternate calls return 0 ready.
46 Mostly for testing the timeout receive call. First call should return
47 something ready and the second should return nothing ready so we can
50 static int em_wait( int fd, void* events, int n, int to ) {
59 //--------------------------------------------------------------------------
65 static int return_value = 0;
68 Test app can call this to have all emulated functions return failure instead
71 static void en_set_retur( int rv ) {
77 static int em_nng_foo() {
78 fprintf( stderr, "emulated functions in play" );
83 Simulated v1 message for receive to return. This needs to match the RMr header
84 so that we can fill in length, type and xaction id things.
87 int32_t mtype; // message type ("long" network integer)
88 int32_t plen; // payload length
89 int32_t rmr_ver; // our internal message version number
90 unsigned char xid[32]; // space for user transaction id or somesuch
91 unsigned char sid[32]; // sender ID for return to sender needs
92 unsigned char src[16]; // name of the sender (source)
93 unsigned char meid[32]; // managed element id.
94 struct timespec ts; // timestamp ???
99 v2 message; should be able to use it for everything that is set up here as
100 we don't add a payload even if setting a v1 type.
102 #define ALT_MSG_VER 1 // alternate every so often
103 #define MSG_VER 2 // default version to insert
105 int32_t mtype; // message type ("long" network integer)
106 int32_t plen; // payload length
107 int32_t rmr_ver; // our internal message version number
108 unsigned char xid[32]; // space for user transaction id or somesuch
109 unsigned char sid[32]; // sender ID for return to sender needs
110 unsigned char src[64]; // name of the sender (source)
111 unsigned char meid[32]; // managed element id.
112 struct timespec ts; // timestamp ???
115 int32_t flags; // HFL_* constants
116 int32_t len0; // length of the RMr header data
117 int32_t len1; // length of the tracing data
118 int32_t len2; // length of data 1 (d1)
119 int32_t len3; // length of data 2 (d2)
124 Receive message must allocate a new buffer and return the pointer into *m.
125 Every 9 messages or so we'll simulate an old version message
127 static int em_nng_recvmsg( nng_socket s, nng_msg ** m, int i ) {
130 static int count = 0; // we'll simulate a message going in by dropping an rmr-ish msg with transaction id only
135 b = (void *) malloc( 2048 );
137 memset( b, 0, 2048 );
139 msg = (struct em_msg *) b;
140 if( count % 10 == 9 ) {
141 //msg->rmr_ver = htonl( MSG_VER );
142 msg->rmr_ver = ALT_MSG_VER; // emulate the bug in RMr v1
144 msg->rmr_ver = htonl( MSG_VER );
146 msg->mtype = htonl( 1 );
147 msg->plen = htonl( 129 );
148 msg->len0 = htonl( sizeof( struct em_msg ) );
149 msg->len1 = htonl( trace_size );
150 snprintf( msg->xid, 32, "%015d", count++ ); // simple transaction id so we can test receive specific and ring stuff
151 snprintf( msg->src, 16, "localhost:4562" ); // set src id (unrealistic) so that rts() can be tested
154 //fprintf( stderr, ">>> simulated received message: %s\n", msg->xid );
158 static void* em_msg_body( nng_msg* msg ) {
159 return (void *) msg; // we don't manage a real msg, so body is just the buffer we allocated
162 static size_t em_msg_len( const nng_msg* msg ) {
171 static int em_nng_pull_open(nng_socket * s ) {
174 static int em_nng_pull0_open(nng_socket * s ) {
177 static int em_nng_listen(nng_socket s, const char * c, nng_listener * l, int i ) {
180 static int em_nng_close(nng_socket s ) {
183 static int em_nng_push0_open(nng_socket * s ) {
186 static int em_nng_dial(nng_socket s, const char * c, nng_dialer * d, int i ) {
187 //fprintf( stderr, "<info> === simulated dialing: %s\n", c );
190 static int em_nng_setopt(nng_socket s, const char * c, const void * p, size_t t ) {
193 static int em_nng_sub_open(nng_socket * s ) {
196 static int em_nng_sub0_open(nng_socket * s ) {
199 static int em_nng_recv(nng_socket s, void * v, size_t * t, int i ) {
202 static int em_nng_send( nng_socket s, void* m, int l, int f ) {
207 Emulate sending a message. If the global em_send_failures is set,
208 then every so often we fail with an EAGAIN to drive that part
211 static int em_sendmsg( nng_socket s, nng_msg* m, int i ) {
212 static int count = 0;
214 if( em_send_failures && (count++ % 15 == 14) ) {
215 //fprintf( stderr, ">>>> failing send\n\n" );
222 static void* em_nng_alloc( size_t len ) {
223 return malloc( len );
226 static int em_nng_msg_alloc( nng_msg** mp, size_t l ) {
229 if( !mp || return_value != 0 ) {
233 p = (void *) malloc( sizeof( char ) * l );
240 We just free the buffer here as it was a simple malloc.
242 static void em_nng_free( void* p, size_t l ) {
244 //fprintf( stderr, ">>>>> not freed: %p\n", p );
248 static void em_nng_msg_free( void* p ) {
250 //fprintf( stderr, ">>>>> not freed: %p\n", p );
255 static int em_dialer_create( void* d, nng_socket s, char* stuff ) {
256 //fprintf( stderr, ">>>> emulated dialer create\n\n" );
260 static int em_dialer_start( nng_dialer d, int i ) {
261 //fprintf( stderr, ">>>> emulated dialer start\n\n" );
266 static int em_dialer_setopt_ms( nng_dialer dialer, void* option, int ms ) {
270 static int em_nng_getopt_int( nng_socket s, void* con, int* target ) {
279 // nng redefines some of these to point directly to various 'versions' of the function (ugg, function versions, really?)
283 #undef nng_pull0_open
286 #undef nng_getopt_int
287 #undef nng_push0_open
295 #define nng_msg_alloc em_nng_msg_alloc
296 #define nng_recvmsg em_nng_recvmsg
297 #define nng_free em_nng_free
298 #define nng_free em_nng_free
299 #define nng_msg_free em_nng_msg_free
300 #define nng_pull_open em_nng_pull_open
301 #define nng_pull0_open em_nng_pull0_open
302 #define nng_listen em_nng_listen
303 #define nng_close em_nng_close
304 #define nng_getopt_int em_nng_getopt_int
305 #define nng_push0_open em_nng_push0_open
306 #define nng_dial em_nng_dial
307 #define nng_setopt em_nng_setopt
308 #define nng_sub_open em_nng_sub_open
309 #define nng_sub0_open em_nng_sub0_open
310 #define nng_recv em_nng_recv
311 #define nng_send em_nng_send
312 #define nng_sendmsg em_sendmsg
313 #define nng_alloc em_nng_alloc
314 #define nng_free em_nng_free
315 #define nng_dialer_setopt_ms em_dialer_setopt_ms
316 #define nng_dialer_start em_dialer_start
317 #define nng_dialer_create em_dialer_create
318 #define nng_msg_body em_msg_body
319 #define nng_msg_len em_msg_len
325 // ----------------------- emulated nano functions --------------------------
326 struct em_nn_msghdr {
330 static int em_nn_socket (int domain, int protocol ) {
336 static int em_nn_close (int s ) {
340 static int em_nn_setsockopt (int s, int level, int option, const void *optval, size_t optvallen ) {
344 static int em_nn_getsockopt (int s, int level, int option, void *optval, size_t *optvallen ) {
348 static int em_nn_bind (int s, const char *addr ) {
349 fprintf( stderr, ">>> ===== emulated bind called ====\n" );
353 static int em_nn_connect (int s, const char *addr ) {
357 static int em_nn_shutdown (int s, int how ) {
361 static int em_nn_send (int s, const void *buf, size_t len, int flags ) {
365 static int em_nn_recv (int s, void *buf, size_t len, int flags ) {
369 static int em_sendmsg (int s, const struct em_nn_msghdr *msghdr, int flags ) {
373 static int em_nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags ) {
378 #define nn_socket em_nn_socket
379 #define nn_close em_nn_close
380 #define nn_setsockopt em_nn_setsockopt
381 #define nn_getsockopt em_nn_getsockopt
382 #define nn_bind em_nn_bind
383 #define nn_connect em_nn_connect
384 #define nn_shutdown em_nn_shutdown
385 #define nn_send em_nn_send
386 #define nn_recv em_nn_recv
387 #define nn_sendmsg em_nn_sendmsg
388 #define nn_recvmsg em_nn_recvmsg