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
60 void spew( char* buf, int len ) {
62 char wbuf[1024]; // slower, but buffer so that mult writers to the tty don't jumble (too much)
66 for( i = 0; i < len; i++ ) {
68 fprintf( stderr, "%s\n", wbuf );
71 sprintf( bbuf, "%02x ", (unsigned char) *(buf+i) );
75 fprintf( stderr, "%s\n", wbuf );
79 Parse n bytes and generate a very simplistic checksum.
82 static int sum( char* bytes, int len ) {
87 sum += *(bytes++) + i;
95 Split the message at the first sep and return a pointer to the first
98 static char* split( char* str, char sep ) {
101 s = strchr( str, sep );
107 fprintf( stderr, "<RCVR> no pipe in message: (%s)\n", str );
112 Generate all buffers that will be combined into a single message
113 payload. This is a random set of bytes into payload and then populate
114 the header with the payload length and chksum. The header generated is
115 placed into a fixed length buffer and consists of three values:
116 checksum result of payload
117 header size (the fixed size, though info is a string)
120 The message can be validated by computing the checksum of the
121 message after the HDR_SIZE, and comparing that with the value
122 passed. The values in the header are all ASCII so they can
123 easily be printed on receipt as a debugging step if needed.
125 hs_over and ds_over allow the caller to override the header and data
126 size constants if set to a positive number
128 The return value is the size of the message payload needed to
129 hold both the header and the payload.
131 int generate_payload( char* hdr, char* data, int hs_over, int ds_over ) {
138 hsize = hs_over <= 0 ? HDR_SIZE : hs_over; // set values from overrides or defaults
139 dsize = ds_over <= 0 ? DATA_SIZE : ds_over;
141 memset( hdr, 0, sizeof( char ) * hsize );
142 for( i = 0; i < dsize; i++ ) {
147 sv = sum( data, dsize );
148 snprintf( hdr, sizeof( char ) * hsize, "%d %d %d |", sv, hsize, dsize );
150 return hsize + dsize;
154 Generate a header for a given payload buffer. THe header size and data size
155 override values default to the HDR_SIZE and DATA_SIZE constants if a value
156 is <= 0; The data is checksummed and the header buffer is populated
157 (see generate_payload() for detailed description.
159 The return is the number of bytes required for the full payload of both
162 int generate_header( char* hdr, char* data, int hs_over, int ds_over ) {
168 hsize = hs_over <= 0 ? HDR_SIZE : hs_over; // set values from overrides or defaults
169 dsize = ds_over <= 0 ? DATA_SIZE : ds_over;
171 memset( hdr, 0, sizeof( char ) * hsize );
172 sv = sum( data, dsize );
173 wrote = snprintf( hdr, sizeof( char ) * hsize, "%d %d %d |", sv, hsize, dsize );
174 if( wrote >= hsize ) {
175 fprintf( stderr, "<ERR> header overflow\n" );
179 return hsize + dsize;
183 Convenience function to push a header/data into an RMR mbuf. It is assumed that the
184 mbuf is large enough; no checks are made. If either length is <= 0, then the
185 default (constant value) is used.
187 void fill_payload( rmr_mbuf_t* msg, char* hdr, int hdr_len, char *data, int data_len ) {
191 fprintf( stderr, "<TEST> fill payload: msg passed in was nil\n" );
195 hdr_len = hdr_len <= 0 ? HDR_SIZE : hdr_len; // set values from input; else use defaults
196 data_len = data_len <= 0 ? DATA_SIZE : data_len;
198 if( hdr_len <= 0 || data_len <= 0 ) {
199 fprintf( stderr, "<TEST> fill payload: header or date len invalid: hdr=%d data=%d\n", hdr_len, data_len );
203 payload = msg->payload;
205 memcpy( payload, hdr, hdr_len > 0 ? hdr_len : HDR_SIZE );
207 memcpy( payload, data, data_len > 0 ? data_len : DATA_SIZE );
211 This function accepts an RMR message payload assumed to be header and user data, in the
212 format: <hdr><data> where <hdr> consists of a string with three space separated values:
218 ensure that the rmr_len matches the header size and data size which are parsed from
219 the message. If sizes match, a checksum is performed on the data and the result
220 compared to the checksum value in the header.
222 int validate_msg( char* buf, int rmr_len ) {
224 char* tok_mark = NULL;
226 char* ohdr = NULL; // original header as we trash the header parsing it
227 int ex_sv; // expected checksum value (pulled from received header)
228 int sv; // computed checksum value
229 int ex_mlen = 0; // expected msg_len (computed from the header, compared with rmr_len)
230 int hdr_len; // length of header to skip
231 int data_len; // length of data received
235 if( buf == 0 && rmr_len <= 0 ) {
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 );
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, "[CONT] header isn't printable\n" );
289 fprintf( stderr, "[CONT] header: (%s)\n", ohdr );
290 fprintf( stderr, "[CONT] 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, "[FAIL] data checksum mismatch, got %d, expected %d. header: %s\n", sv, ex_sv, ohdr );