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

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

fix the 1.04 bencode errors reported in the forums this morning. add regression tests.

File size: 7.2 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
140testString( const char * str, int isGood )
141{
142    benc_val_t val;
143    const uint8_t * end = NULL;
144    char * saved;
145    const size_t len = strlen( str );
146    int savedLen;
147    int err = tr_bencParse( str, str+len, &val , &end );
148    if( !isGood ) {
149        check( err );
150    } else {
151        check( !err );
152        check( end == (const uint8_t*)str + len );
153        saved = tr_bencSave( &val, &savedLen );
154        check( !strcmp( saved, str ) );
155        check( len == (size_t)savedLen );
156        tr_free( saved );
157        tr_bencFree( &val );
158    }
159    return 0;
160}
161
162static int
163testParse( void )
164{
165    benc_val_t val;
166    benc_val_t * child;
167    benc_val_t * child2;
168    uint8_t buf[512];
169    const uint8_t * end;
170    int err;
171    int len;
172    char * saved;
173
174    snprintf( (char*)buf, sizeof( buf ), "i64e" );
175    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
176    check( !err );
177    check( tr_bencGetInt( &val ) == 64 );
178    check( end == buf + 4 );
179    tr_bencFree( &val );
180
181    snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" );
182    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
183    check( !err );
184    check( end == buf + strlen( (char*)buf ) );
185    check( val.val.l.count == 3 );
186    check( tr_bencGetInt( &val.val.l.vals[0] ) == 64 );
187    check( tr_bencGetInt( &val.val.l.vals[1] ) == 32 );
188    check( tr_bencGetInt( &val.val.l.vals[2] ) == 16 );
189    saved = tr_bencSave( &val, &len );
190    check( !strcmp( saved, (char*)buf ) );
191    tr_free( saved );
192    tr_bencFree( &val );
193
194    end = NULL;
195    snprintf( (char*)buf, sizeof( buf ), "lllee" );
196    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val , &end );
197    check( err );
198    check( end == NULL );
199
200    end = NULL;
201    snprintf( (char*)buf, sizeof( buf ), "le" );
202    err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
203    check( !err );
204    check( end == buf + 2 );
205    saved = tr_bencSave( &val, &len );
206    check( !strcmp( saved, "le" ) );
207    tr_free( saved );
208    tr_bencFree( &val );
209
210    if(( err = testString( "llleee", TRUE )))
211        return err;
212    if(( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE )))
213        return err;
214    if(( err = testString( "d4:spaml1:a1:bee", TRUE )))
215        return err;
216#if 0
217    if(( err = testString( "d9:publisher3:bob18:publisher.location4:home17:publisher-webpage15:www.example.come", TRUE )))
218        return err;
219#endif
220    if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
221        return err;
222    if(( err = testString( "d1:ai0e1:be", FALSE ))) /* odd number of children */
223        return err;
224    if(( err = testString( "", FALSE )))
225        return err;
226
227    /* nested containers
228     * parse an unsorted dict
229     * save as a sorted dict */
230    end = NULL;
231    snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" );
232    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
233    check( !err );
234    check( end == buf + strlen( (const char*)buf ) );
235    check(( child = tr_bencListGetNthChild( &val, 0 )));
236    check(( child2 = tr_bencListGetNthChild( child, 0 )));
237    saved = tr_bencSave( &val, &len );
238    check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) );
239    tr_free( saved );
240    tr_bencFree( &val );
241
242    return 0;
243}
244
245static int
246testStackSmash( void )
247{
248    int i;
249    int len;
250    int depth;
251    int err;
252    uint8_t * in;
253    const uint8_t * end;
254    benc_val_t val;
255    char * saved;
256
257    depth = 1000000;
258    in = tr_new( uint8_t, depth*2 + 1 );
259    for( i=0; i<depth; ++i ) {
260        in[i] = 'l';
261        in[depth+i] = 'e';
262    }
263    in[depth*2] = '\0';
264    err = tr_bencParse( in, in+(depth*2), &val, &end );
265    check( !err );
266    check( end == in+(depth*2) );
267    saved = tr_bencSave( &val, &len );
268    check( !strcmp( saved, (char*)in ) );
269    tr_free( in );
270    tr_free( saved );
271    tr_bencFree( &val );
272
273    return 0;
274}
275
276
277int
278main( void )
279{
280    int i;
281
282    if(( i = testInt( )))
283        return i;
284
285    if(( i = testStr( )))
286        return i;
287
288    if(( i = testParse( )))
289        return i;
290
291    if(( i = testStackSmash( )))
292        return i;
293
294    return 0;
295}
Note: See TracBrowser for help on using the repository browser.