fix(send): Add second key lookup if sub-id is set
[ric-plt/lib/rmr.git] / test / test_nng_em.c
1 /*
2 ==================================================================================
3         Copyright (c) 2019 Nokia
4         Copyright (c) 2018-2019 AT&T Intellectual Property.
5
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
9
10            http://www.apache.org/licenses/LICENSE-2.0
11
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 ==================================================================================
18 */
19
20 /*
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
25                                 poll related testing.
26
27                                 This module must be directly included to be used.
28         Date:           11 February 2019
29         Author:         E. Scott Daniels
30 */
31
32 // ---------------------- emulated nng functions ---------------------------
33
34
35 #ifndef _em_nn
36 #define _em_nn
37
38 static int em_send_failures = 0;        // test programme can set this to emulate eagain send failures
39 static int em_timeout = -1;                     // set by set socket option
40
41 // ----------- epoll emulation ---------------------------------------------
42
43 // CAUTION: sys/epoll.h must be included before this define and function will properly compile.
44 #define epoll_wait em_wait
45 /*
46         Every other call returns 1 ready; alternate calls return 0 ready.
47         Mostly for testing the timeout receive call. First call should return
48         something ready and the second should return nothing ready so we can
49         drive both cases.
50 */
51 static int em_wait( int fd, void* events, int n, int to ) {
52         static int ready = 0;
53
54         ready = !ready;
55         return ready;
56 }
57
58
59
60 /*
61         Simulated v1 message for receive to return. This needs to match the RMr header
62         so that we can fill in length, type and xaction id things.
63 #define MSG_VER 1
64 struct em_msg {
65         int32_t mtype;                                          // message type  ("long" network integer)
66         int32_t plen;                                           // payload length
67         int32_t rmr_ver;                                        // our internal message version number
68         unsigned char xid[32];                          // space for user transaction id or somesuch
69         unsigned char sid[32];                          // sender ID for return to sender needs
70         unsigned char src[16];                          // name of the sender (source)
71         unsigned char meid[32];                         // managed element id.
72         struct timespec ts;                                     // timestamp ???
73 };
74 */
75
76 /*
77         v2 message; should be able to use it for everything that is set up here as
78         we don't add a payload even if setting a v1 type.
79 */
80 #define ALT_MSG_VER 1   // alternate every so often
81 #define MSG_VER 2               // default version to insert
82 struct em_msg {
83         int32_t mtype;                                          // message type  ("long" network integer)
84         int32_t plen;                                           // payload length
85         int32_t rmr_ver;                                        // our internal message version number
86         unsigned char xid[32];                          // space for user transaction id or somesuch
87         unsigned char sid[32];                          // sender ID for return to sender needs
88         unsigned char src[64];                          // name of the sender (source)
89         unsigned char meid[32];                         // managed element id.
90         struct timespec ts;                                     // timestamp ???
91
92                                             // V2 extension
93         int32_t flags;                      // HFL_* constants
94         int32_t len0;                       // length of the RMr header data
95         int32_t len1;                       // length of the tracing data
96         int32_t len2;                       // length of data 1 (d1)
97         int32_t len3;                       // length of data 2 (d2)
98
99 };
100
101 static int return_value = 0;
102
103 //--------------------------------------------------------------------------
104 #ifdef EMULATE_NNG
105 struct nn_msghdr {
106         int boo;
107 };
108
109
110 /*
111         Test app can call this to have all emulated functions return failure instead
112         of success.
113 */
114 static void en_set_return( int rv ) {
115         return_value = rv;
116 }
117
118
119
120 static int em_nng_foo() {
121         fprintf( stderr, "emulated functions in play" );
122 }
123
124
125 /*
126         Receive message must allocate a new buffer and return the pointer into *m.
127         Every 9 messages or so we'll simulate an old version message
128 */
129 static int em_nng_recvmsg( nng_socket s, nng_msg ** m, int i ) {
130         void* b;
131         struct em_msg* msg;
132         static int count = 0;                   // we'll simulate a message going in by dropping an rmr-ish msg with transaction id only
133         int trace_size = 0;
134
135         //sleep( 1 );
136
137         b = (void *) malloc( 2048 );
138         if( m != NULL ) {
139                 memset( b, 0, 2048 );
140                 *m = (nng_msg *) b;
141                 msg = (struct em_msg *) b;
142                 if( count % 10  == 9 ) {
143                         //msg->rmr_ver = htonl( MSG_VER );
144                         msg->rmr_ver = ALT_MSG_VER;             // emulate the bug in RMr v1
145                 } else {
146                         msg->rmr_ver = htonl( MSG_VER );
147                 }
148                 msg->mtype = htonl( 1 );
149                 msg->plen = htonl( 220 );
150                 msg->len0 = htonl( sizeof( struct em_msg ) );
151                 msg->len1 = htonl( trace_size );
152                 snprintf( msg->xid, 32, "%015d", count++ );             // simple transaction id so we can test receive specific and ring stuff
153                 snprintf( msg->src, 16, "localhost:4562" );             // set src id (unrealistic) so that rts() can be tested
154         }
155
156         //fprintf( stderr, ">>> simulated received message: %s\n", msg->xid );
157         return return_value;
158 }
159
160 static void* em_msg_body( nng_msg* msg ) {
161         return (void *) msg;                                                            // we don't manage a real msg, so body is just the buffer we allocated
162 }
163
164 static size_t em_msg_len( const nng_msg* msg ) {
165         if( msg ) {
166                 return  2048;
167         }
168
169         return 0;
170 }
171
172
173 static int em_nng_pull_open(nng_socket * s ) {
174         return return_value;
175 }
176 static int em_nng_pull0_open(nng_socket * s ) {
177         return return_value;
178 }
179 static int em_nng_listen(nng_socket s, const char * c, nng_listener * l, int i ) {
180         return return_value;
181 }
182 static int em_nng_close(nng_socket s ) {
183         return return_value;
184 }
185 static int em_nng_push0_open(nng_socket * s ) {
186         return return_value;
187 }
188 static int em_nng_dial(nng_socket s, const char * c, nng_dialer * d, int i ) {
189         //fprintf( stderr, "<info> === simulated dialing: %s\n", c );
190         return return_value;
191 }
192 static int em_nng_setopt(nng_socket s, const char * c, const void * p, size_t t ) {
193         return return_value;
194 }
195 static int em_nng_sub_open(nng_socket * s ) {
196         return return_value;
197 }
198 static int em_nng_sub0_open(nng_socket * s ) {
199         return return_value;
200 }
201 static int em_nng_recv(nng_socket s, void * v, size_t * t, int i ) {
202
203         return return_value;
204 }
205 static int em_nng_send( nng_socket s, void* m, int l, int f ) {
206         return return_value;
207 }
208
209 /*
210         Emulate sending a message. If the global em_send_failures is set,
211         then every so often we fail with an EAGAIN to drive that part
212         of the code in RMr.
213 */
214 static int em_sendmsg( nng_socket s, nng_msg* m, int i ) {
215         static int count = 0;
216
217         if( em_send_failures && (count++ % 15 == 14) ) {
218                 //fprintf( stderr, ">>>> failing send\n\n" );
219                 return NNG_EAGAIN;
220         }
221
222         return return_value;
223 }
224
225 static void* em_nng_alloc( size_t len ) {
226         return malloc( len );
227 }
228
229 static int em_nng_msg_alloc( nng_msg** mp, size_t l ) {
230         void*   p;
231
232         if( !mp || return_value != 0  ) {
233                 return -1;
234         }
235
236         p = (void *) malloc( sizeof( char ) * l );
237         *mp = (nng_msg *) p;
238
239         return return_value;
240 }
241
242 /*
243         We just free the buffer here as it was a simple malloc.
244 */
245 static void em_nng_free( void* p, size_t l ) {
246         if( p ) {
247                 //fprintf( stderr, ">>>>> not freed: %p\n", p );
248                 free( p );
249         }
250 }
251 static void em_nng_msg_free( void* p ) {
252         if( p ) {
253                 //fprintf( stderr, ">>>>> not freed: %p\n", p );
254                 free( p );
255         }
256 }
257
258 static int em_dialer_create( void* d, nng_socket s, char* stuff ) {
259         //fprintf( stderr, ">>>> emulated dialer create\n\n" );
260         return 0;
261 }
262
263 static int em_dialer_start( nng_dialer d, int i ) {
264         //fprintf( stderr, ">>>> emulated dialer start\n\n" );
265         return return_value;
266 }
267
268
269 static int em_dialer_setopt_ms( nng_dialer dialer, void* option, int ms ) {
270         return return_value;
271 }
272
273 static int em_nng_getopt_int( nng_socket s, void* con, int* target ) {
274         if( target ) {
275                 *target = 0;
276         }
277         return return_value;
278 }
279
280
281
282 // nng redefines some of these to point directly to various 'versions' of the function (ugg, function versions, really?)
283 #undef nng_recvmsg
284 #undef nng_free
285 #undef nng_pull_open
286 #undef nng_pull0_open
287 #undef nng_listen
288 #undef nng_close
289 #undef nng_getopt_int
290 #undef nng_push0_open
291 #undef nng_dial
292 #undef nng_setopt
293 #undef nng_sub_open
294 #undef nng_sub0_open
295 #undef nng_recv
296 #undef nng_alloc
297
298 #define nng_msg_alloc em_nng_msg_alloc
299 #define nng_recvmsg em_nng_recvmsg
300 #define nng_free em_nng_free
301 #define nng_free em_nng_free
302 #define nng_msg_free em_nng_msg_free
303 #define nng_pull_open em_nng_pull_open
304 #define nng_pull0_open em_nng_pull0_open
305 #define nng_listen em_nng_listen
306 #define nng_close em_nng_close
307 #define nng_getopt_int em_nng_getopt_int
308 #define nng_push0_open em_nng_push0_open
309 #define nng_dial em_nng_dial
310 #define nng_setopt em_nng_setopt
311 #define nng_sub_open em_nng_sub_open
312 #define nng_sub0_open em_nng_sub0_open
313 #define nng_recv em_nng_recv
314 #define nng_send em_nng_send
315 #define nng_sendmsg em_sendmsg
316 #define nng_alloc em_nng_alloc
317 #define nng_free em_nng_free
318 #define nng_dialer_setopt_ms em_dialer_setopt_ms
319 #define nng_dialer_start em_dialer_start
320 #define nng_dialer_create em_dialer_create
321 #define nng_msg_body em_msg_body
322 #define nng_msg_len em_msg_len
323
324
325 #else
326
327
328 // ----------------------- emulated nano functions --------------------------
329 struct em_nn_msghdr {
330         int dummy;
331 };
332
333 static int em_nn_socket (int domain, int protocol ) {
334         static int s = 1;
335
336         return ++s;
337 }
338
339 static int em_nn_close (int s ) {
340         return 1;
341 }
342
343 //static int em_nn_setsockopt (int s, int level, int option, const void *optval, size_t optvallen ) {
344         //return 1;
345 //}
346
347 static int em_nn_getsockopt (int s, int level, int option, void *optval, size_t *optvallen ) {
348         return 1;
349 }
350
351 static int em_nn_bind (int s, const char *addr ) {
352         //      fprintf( stderr, ">>> ===== emulated bind called ====\n" );
353         return 1;
354 }
355
356 static int em_nn_connect (int s, const char *addr ) {
357         return 1;
358 }
359
360 static int em_nn_shutdown (int s, int how ) {
361         return 1;
362 }
363
364 static int em_nn_send (int s, const void *buf, size_t len, int flags ) {
365         return 1;
366 }
367
368 static int em_nn_recv (int s, void *m, size_t len, int flags ) {
369         void* b;
370         struct em_msg* msg;
371         static int count = 0;                   // we'll simulate a message going in by dropping an rmr-ish msg with transaction id only
372         int trace_size = 0;
373         static int counter = 0;                         // if timeout value is set; we return timeout (eagain) every 3 calls
374
375         if( em_timeout > 0 ) {
376                 counter++;
377                 if( counter % 3 == 0 ) {
378                         return EAGAIN;
379                 }
380         }
381
382         b = (void *) malloc( 2048 );
383         if( m != NULL ) {                                               // blindly we assume this is 2k or bigger
384                 memset( m, 0, 2048 );
385                 msg = (struct em_msg *) m;
386                 if( count % 10  == 9 ) {
387                         //msg->rmr_ver = htonl( MSG_VER );
388                         msg->rmr_ver = ALT_MSG_VER;             // emulate the bug in RMr v1
389                 } else {
390                         msg->rmr_ver = htonl( MSG_VER );
391                 }
392                 msg->mtype = htonl( 1 );
393                 msg->plen = htonl( 220 );
394                 msg->len0 = htonl( sizeof( struct em_msg ) );
395                 msg->len1 = htonl( trace_size );
396                 snprintf( msg->xid, 32, "%015d", count++ );             // simple transaction id so we can test receive specific and ring stuff
397                 snprintf( msg->src, 16, "localhost:4562" );             // set src id (unrealistic) so that rts() can be tested
398                 //fprintf( stderr, "<EM>   returning message len=%d\n\n", ntohl( msg->plen ) );
399         } else {
400                 fprintf( stderr, "<EM>   message was nil\n\n" );
401         }
402
403         //fprintf( stderr, ">>> simulated received message: %s len=%d\n", msg->xid, msg->plen );
404         return 2048;
405 }
406
407 static int em_sendmsg (int s, const struct em_nn_msghdr *msghdr, int flags ) {
408         return 1;
409 }
410
411 static int em_nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags ) {
412         return 1;
413 }
414
415 static void em_nn_freemsg( void* ptr ) {
416         return;
417 }
418
419 /*
420         Hacky implementation of set sock opt. We assume value is a pointer to int and ignore size.
421 */
422 static int em_setsockopt( int sock, int foo, int action, int* value, int size ) {
423         if( action ==  NN_RCVTIMEO ) {
424                 em_timeout = *value;
425         }
426 }
427
428
429 // nanomsg
430 #define nn_socket  em_nn_socket
431 #define nn_close  em_nn_close
432 //#define nn_setsockopt  em_nn_setsockopt
433 #define nn_getsockopt  em_nn_getsockopt
434 #define nn_bind  em_nn_bind
435 #define nn_connect  em_nn_connect
436 #define nn_shutdown  em_nn_shutdown
437 #define nn_send  em_nn_send
438 #define nn_recv  em_nn_recv
439 #define nn_sendmsg  em_nn_sendmsg
440 #define nn_recvmsg  em_nn_recvmsg
441 #define nn_setsockopt  em_setsockopt
442 #define nn_freemsg  em_nn_freemsg
443
444 #endif
445
446
447 #endif