source: trunk/libtransmission/bencode-test.c @ 4882

Last change on this file since 4882 was 4882, checked in by charles, 14 years ago

more graceful handling of bad inputs to tr_bencFree(), tr_bencSave(), and tr_bencPrint().

File size: 6.6 KB
Line 
1#include <stdio.h>
2#include "transmission.h"
3#include "bencode.h"
4#include "utils.h" /* tr_free */
5
6#define VERBOSE 0
7
8int test = 0;
9
10#define check(A) { \
11    ++test; \
12    if (A) { \
13        if( VERBOSE ) \
14            fprintf( stderr, "PASS test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
15    } else { \
16        if( VERBOSE ) \
17            fprintf( stderr, "FAIL test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
18        return test; \
19    } \
20}
21
22static int
23testInt( void )
24{
25    uint8_t buf[128];
26    int64_t val;
27    int err;
28    const uint8_t * end;
29
30    /* good int string */
31    snprintf( (char*)buf, sizeof( buf ), "i64e" );
32    err = tr_bencParseInt( buf, buf+4, &end, &val );
33    check( err == 0 );
34    check( val == 64 );
35    check( end == buf + 4 );
36
37    /* missing 'e' */
38    end = NULL;
39    val = 888;
40    err = tr_bencParseInt( buf, buf+3, &end, &val );
41    check( err == TR_ERROR ); 
42    check( val == 888 );
43    check( end == NULL );
44
45    /* empty buffer */
46    err = tr_bencParseInt( buf, buf+0, &end, &val );
47    check( err == TR_ERROR ); 
48    check( val == 888 );
49    check( end == NULL );
50
51    /* bad number */
52    snprintf( (char*)buf, sizeof( buf ), "i6z4e" );
53    err = tr_bencParseInt( buf, buf+5, &end, &val );
54    check( err == TR_ERROR );
55    check( val == 888 );
56    check( end == NULL );
57
58    /* negative number */
59    snprintf( (char*)buf, sizeof( buf ), "i-3e" );
60    err = tr_bencParseInt( buf, buf+4, &end, &val );
61    check( err == TR_OK );
62    check( val == -3 );
63    check( end == buf + 4 );
64
65    /* zero */
66    snprintf( (char*)buf, sizeof( buf ), "i0e" );
67    err = tr_bencParseInt( buf, buf+4, &end, &val );
68    check( err == TR_OK );
69    check( val == 0 );
70    check( end == buf + 3 );
71
72    /* no leading zeroes allowed */
73    val = 0;
74    end = NULL;
75    snprintf( (char*)buf, sizeof( buf ), "i04e" );
76    err = tr_bencParseInt( buf, buf+4, &end, &val );
77    check( err == TR_ERROR );
78    check( val == 0 );
79    check( end == NULL );
80
81    return 0;
82}
83
84static int
85testStr( void )
86{
87    uint8_t buf[128];
88    int err;
89    const uint8_t * end;
90    uint8_t * str;
91    size_t len;
92
93    /* good string */
94    snprintf( (char*)buf, sizeof( buf ), "4:boat" );
95    err = tr_bencParseStr( buf, buf+6, &end, &str, &len );
96    check( err == TR_OK );
97    check( !strcmp( (char*)str, "boat" ) );
98    check( len == 4 );
99    check( end == buf + 6 );
100    tr_free( str );
101    str = NULL;
102    end = NULL;
103    len = 0;
104
105    /* string goes past end of buffer */
106    err = tr_bencParseStr( buf, buf+5, &end, &str, &len );
107    check( err == TR_ERROR );
108    check( str == NULL );
109    check( end == NULL );
110    check( !len );
111
112    /* empty string */
113    snprintf( (char*)buf, sizeof( buf ), "0:" );
114    err = tr_bencParseStr( buf, buf+2, &end, &str, &len );
115    check( err == TR_OK );
116    check( !*str );
117    check( !len );
118    check( end == buf + 2 );
119    tr_free( str );
120    str = NULL;
121    end = NULL;
122    len = 0;
123
124    /* short string */
125    snprintf( (char*)buf, sizeof( buf ), "3:boat" );
126    err = tr_bencParseStr( buf, buf+6, &end, &str, &len );
127    check( err == TR_OK );
128    check( !strcmp( (char*)str, "boa" ) );
129    check( len == 3 );
130    check( end == buf + 5 );
131    tr_free( str );
132    str = NULL;
133    end = NULL;
134    len = 0;
135
136    return 0;
137}
138
139static int
140testParse( void )
141{
142    benc_val_t val;
143    benc_val_t * child;
144    benc_val_t * child2;
145    uint8_t buf[512];
146    const uint8_t * end;
147    int err;
148    int len;
149    char * saved;
150
151    snprintf( (char*)buf, sizeof( buf ), "i64e" );
152    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
153    check( !err );
154    check( tr_bencGetInt( &val ) == 64 );
155    check( end == buf + 4 );
156    tr_bencFree( &val );
157
158    snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" );
159    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
160    check( !err );
161    check( end == buf + strlen( (char*)buf ) );
162    check( val.val.l.count == 3 );
163    check( tr_bencGetInt( &val.val.l.vals[0] ) == 64 );
164    check( tr_bencGetInt( &val.val.l.vals[1] ) == 32 );
165    check( tr_bencGetInt( &val.val.l.vals[2] ) == 16 );
166    saved = tr_bencSave( &val, &len );
167    check( !strcmp( saved, (char*)buf ) );
168    tr_free( saved );
169    tr_bencFree( &val );
170
171    end = NULL;
172    snprintf( (char*)buf, sizeof( buf ), "lllee" );
173    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val , &end );
174    check( err );
175    check( end == NULL );
176
177    end = NULL;
178    snprintf( (char*)buf, sizeof( buf ), "le" );
179    err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
180    check( !err );
181    check( end == buf + 2 );
182    saved = tr_bencSave( &val, &len );
183    check( !strcmp( saved, "le" ) );
184    tr_free( saved );
185    tr_bencFree( &val );
186
187    end = NULL;
188    snprintf( (char*)buf, sizeof( buf ), "llleee" );
189    err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
190    check( !err );
191    check( end == buf + 6 );
192    saved = tr_bencSave( &val, &len );
193    check( !strcmp( saved, "llleee" ) );
194    tr_free( saved );
195    tr_bencFree( &val );
196
197    /* nested containers
198     * parse an unsorted dict
199     * save as a sorted dict */
200    end = NULL;
201    snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" );
202    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
203    check( !err );
204    check( end == buf + strlen( (const char*)buf ) );
205    check(( child = tr_bencListGetNthChild( &val, 0 )));
206    check(( child2 = tr_bencListGetNthChild( child, 0 )));
207    saved = tr_bencSave( &val, &len );
208    check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) );
209    tr_free( saved );
210    tr_bencFree( &val );
211
212    end = NULL;
213    snprintf( (char*)buf, sizeof( buf ), "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e" );
214    err = tr_bencParse( buf, buf+sizeof( buf ), &val, &end );
215    check( !err );
216    check( end == buf + strlen( (const char*)buf ) );
217    tr_bencFree( &val );
218
219    return 0;
220}
221
222static int
223testStackSmash( void )
224{
225    int i;
226    int len;
227    int depth;
228    int err;
229    uint8_t * in;
230    const uint8_t * end;
231    benc_val_t val;
232    char * saved;
233
234    depth = 1000000;
235    in = tr_new( uint8_t, depth*2 + 1 );
236    for( i=0; i<depth; ++i ) {
237        in[i] = 'l';
238        in[depth+i] = 'e';
239    }
240    in[depth*2] = '\0';
241    err = tr_bencParse( in, in+(depth*2), &val, &end );
242    check( !err );
243    check( end == in+(depth*2) );
244    saved = tr_bencSave( &val, &len );
245    check( !strcmp( saved, (char*)in ) );
246    tr_free( in );
247    tr_free( saved );
248    tr_bencFree( &val );
249
250    return 0;
251}
252
253
254int
255main( void )
256{
257    int i;
258
259    if(( i = testInt( )))
260        return i;
261
262    if(( i = testStr( )))
263        return i;
264
265    if(( i = testParse( )))
266        return i;
267
268    if(( i = testStackSmash( )))
269        return i;
270
271    return 0;
272}
Note: See TracBrowser for help on using the repository browser.