/*
==================================================================================
- Copyright (c) 2019 Nokia
+ Copyright (c) 2019 Nokia
Copyright (c) 2018-2019 AT&T Intellectual Property.
Licensed 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
+ 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,
/*
Mnemonic: test_nng_em.c
- Abstract: A nano/NNG message emulator for testing without needing to
+ Abstract: A nano/NNG message emulator for testing without needing to
actually have nanomsg, nng, or external processes.
We also emulate the epoll_wait() function for controlled
poll related testing.
#define _em_nn
static int em_send_failures = 0; // test programme can set this to emulate eagain send failures
+static int em_timeout = -1; // set by set socket option
// ----------- epoll emulation ---------------------------------------------
-// CAUTION: sys/epoll.h must be included before this define and function will properly compile.
+// CAUTION: sys/epoll.h must be included before this define and function will properly compile.
#define epoll_wait em_wait
/*
- Every other call returns 1 ready; alternate calls return 0 ready.
- Mostly for testing the timeout receive call. First call should return
+ Every other call returns 1 ready; alternate calls return 0 ready.
+ Mostly for testing the timeout receive call. First call should return
something ready and the second should return nothing ready so we can
- drive both cases.
+ drive both cases.
*/
static int em_wait( int fd, void* events, int n, int to ) {
static int ready = 0;
-//--------------------------------------------------------------------------
-#ifdef EMULATE_NNG
-struct nn_msghdr {
- int boo;
-};
-
-static int return_value = 0;
-
-/*
- Test app can call this to have all emulated functions return failure instead
- of success.
-*/
-static void en_set_retur( int rv ) {
- return_value = rv;
-}
-
-
-
-static int em_nng_foo() {
- fprintf( stderr, "emulated functions in play" );
-}
-
-
/*
Simulated v1 message for receive to return. This needs to match the RMr header
so that we can fill in length, type and xaction id things.
*/
/*
- v2 message; should be able to use it for everything that is set up here as
+ v2 message; should be able to use it for everything that is set up here as
we don't add a payload even if setting a v1 type.
*/
#define ALT_MSG_VER 1 // alternate every so often
unsigned char meid[32]; // managed element id.
struct timespec ts; // timestamp ???
- // V2 extension
- int32_t flags; // HFL_* constants
- int32_t len0; // length of the RMr header data
- int32_t len1; // length of the tracing data
- int32_t len2; // length of data 1 (d1)
- int32_t len3; // length of data 2 (d2)
+ // V2 extension
+ int32_t flags; // HFL_* constants
+ int32_t len0; // length of the RMr header data
+ int32_t len1; // length of the tracing data
+ int32_t len2; // length of data 1 (d1)
+ int32_t len3; // length of data 2 (d2)
+
+};
+
+static int return_value = 0;
+//--------------------------------------------------------------------------
+#ifdef EMULATE_NNG
+struct nn_msghdr {
+ int boo;
};
+
+/*
+ Test app can call this to have all emulated functions return failure instead
+ of success.
+*/
+static void en_set_return( int rv ) {
+ return_value = rv;
+}
+
+
+
+static int em_nng_foo() {
+ fprintf( stderr, "emulated functions in play" );
+}
+
+
/*
Receive message must allocate a new buffer and return the pointer into *m.
Every 9 messages or so we'll simulate an old version message
msg->rmr_ver = htonl( MSG_VER );
}
msg->mtype = htonl( 1 );
- msg->plen = htonl( 129 );
+ msg->plen = htonl( 220 );
msg->len0 = htonl( sizeof( struct em_msg ) );
msg->len1 = htonl( trace_size );
snprintf( msg->xid, 32, "%015d", count++ ); // simple transaction id so we can test receive specific and ring stuff
return return_value;
}
static int em_nng_recv(nng_socket s, void * v, size_t * t, int i ) {
+
return return_value;
}
static int em_nng_send( nng_socket s, void* m, int l, int f ) {
/*
Emulate sending a message. If the global em_send_failures is set,
- then every so often we fail with an EAGAIN to drive that part
+ then every so often we fail with an EAGAIN to drive that part
of the code in RMr.
*/
static int em_sendmsg( nng_socket s, nng_msg* m, int i ) {
// nng redefines some of these to point directly to various 'versions' of the function (ugg, function versions, really?)
-#undef nng_recvmsg
-#undef nng_free
-#undef nng_pull_open
-#undef nng_pull0_open
-#undef nng_listen
-#undef nng_close
-#undef nng_getopt_int
-#undef nng_push0_open
-#undef nng_dial
-#undef nng_setopt
-#undef nng_sub_open
-#undef nng_sub0_open
-#undef nng_recv
-#undef nng_alloc
+#undef nng_recvmsg
+#undef nng_free
+#undef nng_pull_open
+#undef nng_pull0_open
+#undef nng_listen
+#undef nng_close
+#undef nng_getopt_int
+#undef nng_push0_open
+#undef nng_dial
+#undef nng_setopt
+#undef nng_sub_open
+#undef nng_sub0_open
+#undef nng_recv
+#undef nng_alloc
#define nng_msg_alloc em_nng_msg_alloc
#define nng_recvmsg em_nng_recvmsg
return 1;
}
-static int em_nn_setsockopt (int s, int level, int option, const void *optval, size_t optvallen ) {
- return 1;
-}
+//static int em_nn_setsockopt (int s, int level, int option, const void *optval, size_t optvallen ) {
+ //return 1;
+//}
static int em_nn_getsockopt (int s, int level, int option, void *optval, size_t *optvallen ) {
return 1;
}
static int em_nn_bind (int s, const char *addr ) {
-fprintf( stderr, ">>> ===== emulated bind called ====\n" );
+ // fprintf( stderr, ">>> ===== emulated bind called ====\n" );
return 1;
}
return 1;
}
-static int em_nn_recv (int s, void *buf, size_t len, int flags ) {
- return 1;
+static int em_nn_recv (int s, void *m, size_t len, int flags ) {
+ void* b;
+ struct em_msg* msg;
+ static int count = 0; // we'll simulate a message going in by dropping an rmr-ish msg with transaction id only
+ int trace_size = 0;
+ static int counter = 0; // if timeout value is set; we return timeout (eagain) every 3 calls
+
+ if( em_timeout > 0 ) {
+ counter++;
+ if( counter % 3 == 0 ) {
+ return EAGAIN;
+ }
+ }
+
+ b = (void *) malloc( 2048 );
+ if( m != NULL ) { // blindly we assume this is 2k or bigger
+ memset( m, 0, 2048 );
+ msg = (struct em_msg *) m;
+ if( count % 10 == 9 ) {
+ //msg->rmr_ver = htonl( MSG_VER );
+ msg->rmr_ver = ALT_MSG_VER; // emulate the bug in RMr v1
+ } else {
+ msg->rmr_ver = htonl( MSG_VER );
+ }
+ msg->mtype = htonl( 1 );
+ msg->plen = htonl( 220 );
+ msg->len0 = htonl( sizeof( struct em_msg ) );
+ msg->len1 = htonl( trace_size );
+ snprintf( msg->xid, 32, "%015d", count++ ); // simple transaction id so we can test receive specific and ring stuff
+ snprintf( msg->src, 16, "localhost:4562" ); // set src id (unrealistic) so that rts() can be tested
+ //fprintf( stderr, "<EM> returning message len=%d\n\n", ntohl( msg->plen ) );
+ } else {
+ fprintf( stderr, "<EM> message was nil\n\n" );
+ }
+
+ //fprintf( stderr, ">>> simulated received message: %s len=%d\n", msg->xid, msg->plen );
+ return 2048;
}
static int em_sendmsg (int s, const struct em_nn_msghdr *msghdr, int flags ) {
return 1;
}
-// nanomsg
+static void em_nn_freemsg( void* ptr ) {
+ return;
+}
+
+/*
+ Hacky implementation of set sock opt. We assume value is a pointer to int and ignore size.
+*/
+static int em_setsockopt( int sock, int foo, int action, int* value, int size ) {
+ if( action == NN_RCVTIMEO ) {
+ em_timeout = *value;
+ }
+}
+
+
+// nanomsg
#define nn_socket em_nn_socket
#define nn_close em_nn_close
-#define nn_setsockopt em_nn_setsockopt
+//#define nn_setsockopt em_nn_setsockopt
#define nn_getsockopt em_nn_getsockopt
#define nn_bind em_nn_bind
#define nn_connect em_nn_connect
#define nn_recv em_nn_recv
#define nn_sendmsg em_nn_sendmsg
#define nn_recvmsg em_nn_recvmsg
+#define nn_setsockopt em_setsockopt
+#define nn_freemsg em_nn_freemsg
-#endif
+#endif
#endif