1 // :vim ts=4 sw=4 noet:
3 ==================================================================================
4 Copyright (c) 2019 Nokia
5 Copyright (c) 2018-2019 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
22 Mnemonic: test_support.c
23 Abstract: Support functions for app test programmes.
25 sum() compute a simple checksum over a buffer
26 split() split an ascii buffer at the first |
27 generate_payload() build a header and data buffer generate
28 a random data buffer with a header containing
29 the checksum, and lengths.
30 validate_msg() given a message of <hdr><data> validate
31 that the message is the correct length and chk sum.
34 Author: E. Scott Daniels
46 // defaults if the test app doesn't set these
48 #define HDR_SIZE 64 // the size of the header we place into the message
52 #define MSG_SIZE 1024 // the size of the message that will be sent (hdr+payload)
56 #define DATA_SIZE (HDR_SIZE-HDR_SIZE) // the actual 'data' length returned in the ack msg
59 void spew( char* buf, int len ) {
61 char wbuf[1024]; // slower, but buffer so that mult writers to the tty don't jumble (too much)
65 for( i = 0; i < len; i++ ) {
67 fprintf( stderr, "%s\n", wbuf );
70 sprintf( bbuf, "%02x ", (unsigned char) *(buf+i) );
74 fprintf( stderr, "%s\n", wbuf );
78 Parse n bytes and generate a very simplistic checksum.
81 static int sum( char* bytes, int len ) {
86 sum += *(bytes++) + i;
94 Split the message at the first sep and return a pointer to the first
97 static char* split( char* str, char sep ) {
100 s = strchr( str, sep );
106 fprintf( stderr, "<RCVR> no pipe in message: (%s)\n", str );
111 Generate all buffers that will be combined into a single message
112 payload. This is a random set of bytes into payload and then populate
113 the header with the payload length and chksum. The header generated is
114 placed into a fixed length buffer and consists of three values:
115 checksum result of payload
116 header size (the fixed size, though info is a string)
119 The message can be validated by computing the checksum of the
120 message after the HDR_SIZE, and comparing that with the value
121 passed. The values in the header are all ASCII so they can
122 easily be printed on receipt as a debugging step if needed.
124 hs_over and ds_over allow the caller to override the header and data
125 size constants if set to a positive number
127 The return value is the size of the message payload needed to
128 hold both the header and the payload.
130 int generate_payload( char* hdr, char* data, int hs_over, int ds_over ) {
137 hsize = hs_over <= 0 ? HDR_SIZE : hs_over; // set values from overrides or defaults
138 dsize = ds_over <= 0 ? DATA_SIZE : ds_over;
140 memset( hdr, 0, sizeof( char ) * hsize );
141 for( i = 0; i < dsize; i++ ) {
146 sv = sum( data, dsize );
147 snprintf( hdr, sizeof( char ) * hsize, "%d %d %d |", sv, hsize, dsize );
149 return hsize + dsize;
153 Generate a header for a given payload buffer. THe header size and data size
154 override values default to the HDR_SIZE and DATA_SIZE constants if a value
155 is <= 0; The data is checksummed and the header buffer is populated
156 (see generate_payload() for detailed description.
158 The return is the number of bytes required for the full payload of both
161 int generate_header( char* hdr, char* data, int hs_over, int ds_over ) {
167 hsize = hs_over <= 0 ? HDR_SIZE : hs_over; // set values from overrides or defaults
168 dsize = ds_over <= 0 ? DATA_SIZE : ds_over;
170 memset( hdr, 0, sizeof( char ) * hsize );
171 sv = sum( data, dsize );
172 wrote = snprintf( hdr, sizeof( char ) * hsize, "%d %d %d |", sv, hsize, dsize );
173 if( wrote >= hsize ) {
174 fprintf( stderr, "<ERR> header overflow\n" );
178 return hsize + dsize;
182 Convenience function to push a header/data into an RMR mbuf. It is assumed that the
183 mbuf is large enough; no checks are made. If either length is <= 0, then the
184 default (constant value) is used.
186 void fill_payload( rmr_mbuf_t* msg, char* hdr, int hdr_len, char *data, int data_len ) {
190 fprintf( stderr, "<TEST> fill payload: msg passed in was nil\n" );
194 hdr_len = hdr_len <= 0 ? HDR_SIZE : hdr_len; // set values from input; else use defaults
195 data_len = data_len <= 0 ? DATA_SIZE : data_len;
197 if( hdr_len <= 0 || data_len <= 0 ) {
198 fprintf( stderr, "<TEST> fill payload: header or date len invalid: hdr=%d data=%d\n", hdr_len, data_len );
202 payload = msg->payload;
204 memcpy( payload, hdr, hdr_len > 0 ? hdr_len : HDR_SIZE );
206 memcpy( payload, data, data_len > 0 ? data_len : DATA_SIZE );
210 This function accepts an RMR message payload assumed to be header and user data, in the
211 format: <hdr><data> where <hdr> consists of a string with three space separated values:
217 ensure that the rmr_len matches the header size and data size which are parsed from
218 the message. If sizes match, a checksum is performed on the data and the result
219 compared to the checksum value in the header.
221 int validate_msg( char* buf, int rmr_len ) {
223 char* tok_mark = NULL;
225 char* ohdr = NULL; // original header as we trash the header parsing it
226 int ex_sv; // expected checksum value (pulled from received header)
227 int sv; // computed checksum value
228 int ex_mlen = 0; // expected msg_len (computed from the header, compared with rmr_len)
229 int hdr_len; // length of header to skip
230 int data_len; // length of data received
234 if( buf == 0 && rmr_len <= 0 ) {
235 fprintf( stderr, "<TEST> validate msg: nil buffer or no len: %p len=%d\n", buf, rmr_len );
239 for( i = 0; i < HDR_SIZE; i++ ) { // for what we consider the dfault header, we must see ALL ascci and a trail zero before end
240 if( *(buf+i) == 0 ) {
245 if( ! isprint( *buf ) ) { // we expect the header to be a zero terminated string
246 fprintf( stderr, "<TEST> validate msg: header is not completely ASCII i=%d\n", i );
247 spew( buf, rmr_len > 64 ? 64 : rmr_len );
253 fprintf( stderr, "<TEST> validate msg: didn't find an acceptable header (not nil terminated)\n" );
257 ohdr = strdup( buf ); // must copy so we can trash
260 for( i = 0; i < 3; i++ ) {
261 tok = strtok_r( search_start, " ", &tok_mark );
270 hdr_len = atoi( tok ); // capture header length
271 ex_mlen = hdr_len; // start to compute total msg len
276 data_len = atoi( tok ); // add data length
283 if( ex_mlen != rmr_len ) {
284 fprintf( stderr, "[FAIL] received message length did not match hdr+data lengths, rmr_len=%d data follows:\n", rmr_len );
285 if( ! isprint( *ohdr ) ) {
286 fprintf( stderr, "<TEST> validate msg: header isn't printable\n" );
287 spew( ohdr, rmr_len > 64 ? 64 : rmr_len );
289 fprintf( stderr, "<TEST> validate msg: header: (%s)\n", ohdr );
290 fprintf( stderr, "<TEST> validate msg: computed length: %d (expected)\n", ex_mlen );
297 fprintf( stderr, "[OK] message lengths are good\n" );
301 //fprintf( stderr, ">>>> computing chksum starting at %d for %d bytes\n", hdr_len, data_len );
302 sv = sum( tok, data_len ); // compute checksum of data portion
305 fprintf( stderr, "<TEST> validate msg: data checksum mismatch, got %d, expected %d. header: %s\n", sv, ex_sv, ohdr );