blob: d2977f68256caca9dd136d118d37332da9e6deca [file] [log] [blame]
/*
==================================================================================
Copyright (c) 2020 Nokia
Copyright (c) 2020 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
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.
==================================================================================
*/
/*
Mnemonic: test_common_em.c
Abstract: This supplies some dummy emulation functions that are common
to any of the emulation code. This file should be inlucded
by the emulation code, and not the test programme.
This also includes dummy struct defs so that we can simulate
returning messages and message buffers and some control
functions which can be used to taylor the emulation behavour
during the test.
Date: 21 February 2020
Author: E. Scott Daniels
*/
#ifndef _em_common_c
#define _em_common_c
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
static int em_mtc_msgs = 0; // set to generate 'received' messages with mt-call header data
static int return_value = 0; // functions should return this value
static int rcv_count = 0; // receive counter for transaction id to allow test to rest
static int rcv_delay = 0; // forced delay before call to rcvmsg starts to work
static int gates_ok = 0;
static pthread_mutex_t rcv_gate;
static int em_gen_long_hostname = 0; // if set the emulated hostname generates a longer name (>40 char)
/*
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.
#define MSG_VER 1
struct em_msg {
int32_t mtype; // message type ("long" network integer)
int32_t plen; // payload length
int32_t rmr_ver; // our internal message version number
unsigned char xid[32]; // space for user transaction id or somesuch
unsigned char sid[32]; // sender ID for return to sender needs
unsigned char src[16]; // name of the sender (source)
unsigned char meid[32]; // managed element id.
struct timespec ts; // timestamp ???
};
*/
/*
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
#define MSG_VER 3 // default version to insert
struct em_msg {
int32_t mtype; // message type ("long" network integer)
int32_t plen; // payload length
int32_t rmr_ver; // our internal message version number
unsigned char xid[32]; // space for user transaction id or somesuch
unsigned char sid[32]; // sender ID for return to sender needs
unsigned char src[64]; // name of the sender (source)
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)
int32_t sub_id; // subscription id (-1 invalid)
// V3 stuff
unsigned char srcip[64]; // sender ID for return to sender needs
};
// -- emulation control functions ------------------------------------------------------
/*
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" );
}
/*
Turns on/off the generation of multi-threaded call messages
*/
static int em_set_mtc_msgs( int state ) {
em_mtc_msgs = state;
}
/*
Returns the size of the header we inserted
*/
static int em_hdr_size() {
if( em_mtc_msgs ) {
return (int) sizeof( struct em_msg ) + 4;
}
return (int) sizeof( struct em_msg );
}
static void em_set_rcvcount( int v ) {
rcv_count = v;
}
static void em_set_rcvdelay( int v ) {
if( v < 0 ) {
fprintf( stderr, "<EM> ##ERR## attempt to set receive delay with invalid value was ignored: %d seconds\n", v );
return;
}
fprintf( stderr, "<EM> receive delay is now %d seconds\n", v );
rcv_delay = v;
}
static void em_start() {
if( ! gates_ok ) {
pthread_mutex_init( &rcv_gate, NULL );
gates_ok = 1;
}
}
// ----------- gethostname emulation ---------------------------------------
#define gethostname em_gethostname
static int em_gethostname( char* buf, size_t len ) {
if( len < 1 ) {
errno = EINVAL;
return 1;
}
if( em_gen_long_hostname ) {
snprintf( buf, len, "hostname-which-is-long-a860430b890219-dfw82" );
} else {
snprintf( buf, len, "em-hostname" );
}
return 0;
}
static int em_set_long_hostname( int v ) {
em_gen_long_hostname = !!v;
}
// ----------- epoll emulation ---------------------------------------------
// CAUTION: sys/epoll.h must be included before these define for functions
// to properly compile.
//
#include <sys/epoll.h>
#define epoll_wait em_wait
#define epoll_ctl em_ep_ctl
#define epoll_create em_ep_create
/*
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.
*/
static int em_wait( int fd, void* events, int n, int to ) {
static int ready = 0;
ready = !ready;
return ready;
}
static int em_ep_ctl( int epfd, int op, int fd, struct epoll_event *event ) {
return 0;
}
static int em_ep_create( int size ) {
return 0;
}
#endif