1/* @(#) unit test of udpxy data-stream cache */
2
3#include <sys/types.h>
4#include <stdio.h>
5#include <assert.h>
6#include <stdlib.h>
7
8#include "util.h"
9#include "cache.h"
10#include "dpkt.h"
11#include "udpxy.h"
12
13extern FILE* g_flog;
14
15extern const char CMD_UDP[];
16
17#define BUFSZ       (64 * 1024)
18#define NUM_MSGS    (BUFSZ / ETHERNET_MTU)
19#define CACHE_MAXSZ (BUFSZ * 10)
20
21static struct dscache* cache = NULL;
22static struct dstream_ctx spc;
23
24
25static int
26test_init()
27{
28    int rc = 0;
29
30    (void) fprintf( g_flog, "\n%s: TEST STARTED\n", __func__ );
31
32    rc = init_dstream_ctx( &spc, CMD_UDP, NULL, NUM_MSGS );
33    if( 0 != rc )
34        return -1;
35
36    cache = dscache_init( CACHE_MAXSZ, &spc, BUFSZ, 3 );
37    if( NULL == cache )
38        return -1;
39
40    dscache_free( cache );
41    free_dstream_ctx( &spc );
42
43    (void) fprintf( g_flog, "\n%s: TEST FINISHED\n", __func__ );
44    return 0;
45}
46
47
48static void
49dump_chunk( FILE* out, const struct chunk* chnk,
50            const char* tag )
51{
52    assert( out && chnk );
53
54    (void) fprintf( out, "%s(%p)=[l:%ld,u:%ld,n:%p]\n",
55            (tag ? tag : "chunk"), (const void*)chnk,
56            (long)chnk->length,
57            (long)chnk->used_length, (const void*)chnk->next );
58}
59
60
61
62static int
63test_read_into()
64{
65    int rc = 0, numiter = 10;
66    ssize_t i;
67    struct chunk *rchnk = NULL, *wchnk = NULL;
68
69    (void) fprintf( g_flog, "\n%s: TEST STARTED\n", __func__ );
70
71    rc = init_dstream_ctx( &spc, CMD_UDP, NULL, NUM_MSGS );
72    if( 0 != rc )
73        return -1;
74
75    cache = dscache_init( CACHE_MAXSZ, &spc, BUFSZ, 3 );
76    if( NULL == cache )
77        return -1;
78
79    do {
80        (void) fprintf( g_flog, "%d: -------- BEGIN\n",
81                numiter );
82
83        rchnk = dscache_rget( cache, &rc );
84        if( !rchnk ) break;
85
86        dump_chunk( g_flog, rchnk, "R" );
87
88        for( i = 0; i < (rchnk->length - 64); ++i )
89            rchnk->data[i] = 'U';
90
91        (void) fprintf( g_flog, "%d: data updated [%ld]\n",
92                numiter, (long)i );
93
94        rc = dscache_rset( cache, i );
95        if( 0 != rc ) break;
96
97        wchnk = dscache_wget( cache, &rc );
98        if( !wchnk ) break;
99
100        (void) fprintf( g_flog, "%d: grabbed W-chunk(%p)\n",
101                numiter, (const void*)wchnk );
102        dump_chunk( g_flog, wchnk, "W" );
103
104        for( i = 0; (i < wchnk->used_length) && !rc; ++i ) {
105            if( 'U' != wchnk->data[i] )
106                rc = 1;
107        }
108
109        (void) fprintf( g_flog, "%d: W-chunk(%p) read\n",
110                numiter, (const void*)wchnk );
111
112        (void) fprintf( g_flog, "%d: -------- END\n", numiter );
113    } while( --numiter > 0 );
114
115    if( rc ) {
116        (void) fprintf( g_flog, "Error = [%d]\n", rc );
117    }
118
119    dscache_free( cache );
120    free_dstream_ctx( &spc );
121
122    (void) fprintf( g_flog, "\n%s: TEST FINISHED\n", __func__ );
123    return rc;
124}
125
126
127int
128main( int argc, char* const argv[] )
129{
130    int rc = 0, tlevel = 0;
131    const char* trace_str = getenv( "UDPXY_TRACE_CACHE" );
132
133
134    (void)(&argc && &argv);
135
136    g_flog = stderr;
137    if( trace_str ) {
138        tlevel = atoi( trace_str );
139        if( !tlevel && '0' != trace_str[0] ) {
140            (void) fprintf( g_flog, "Error specifying trace level [%s]\n",
141                    trace_str );
142            return 1;
143        }
144
145        set_cache_trace( tlevel );
146    }
147
148    do {
149        if( 0 != (rc = test_init()) )
150            break;
151        if( 0 != (rc = test_read_into()) )
152            break;
153
154    } while(0);
155
156    return rc;
157}
158
159
160/* __EOF__ */
161
162