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

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

#394: resume files should use original name instead of hash name

  • Property svn:keywords set to Date Rev Author Id
File size: 9.0 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    tr_benc 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    tr_benc val;
166    tr_benc * child;
167    tr_benc * child2;
168    uint8_t buf[512];
169    const uint8_t * end;
170    int err;
171    int len;
172    int64_t i;
173    char * saved;
174
175    snprintf( (char*)buf, sizeof( buf ), "i64e" );
176    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
177    check( !err );
178    check( tr_bencGetInt( &val, &i ) );
179    check( i == 64 );
180    check( end == buf + 4 );
181    tr_bencFree( &val );
182
183    snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" );
184    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
185    check( !err );
186    check( end == buf + strlen( (char*)buf ) );
187    check( val.val.l.count == 3 );
188    check( tr_bencGetInt( &val.val.l.vals[0], &i ) );
189    check( i == 64 );
190    check( tr_bencGetInt( &val.val.l.vals[1], &i ) );
191    check( i == 32 );
192    check( tr_bencGetInt( &val.val.l.vals[2], &i ) );
193    check( i == 16 );
194    saved = tr_bencSave( &val, &len );
195    check( !strcmp( saved, (char*)buf ) );
196    tr_free( saved );
197    tr_bencFree( &val );
198
199    end = NULL;
200    snprintf( (char*)buf, sizeof( buf ), "lllee" );
201    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val , &end );
202    check( err );
203    check( end == NULL );
204
205    end = NULL;
206    snprintf( (char*)buf, sizeof( buf ), "le" );
207    err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
208    check( !err );
209    check( end == buf + 2 );
210    saved = tr_bencSave( &val, &len );
211    check( !strcmp( saved, "le" ) );
212    tr_free( saved );
213    tr_bencFree( &val );
214
215    if(( err = testString( "llleee", TRUE )))
216        return err;
217    if(( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE )))
218        return err;
219    if(( err = testString( "d4:spaml1:a1:bee", TRUE )))
220        return err;
221    if(( err = testString( "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", TRUE )))
222        return err;
223    if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
224        return err;
225    if(( err = testString( "d1:ai0e1:be", FALSE ))) /* odd number of children */
226        return err;
227    if(( err = testString( "", FALSE )))
228        return err;
229    if(( err = testString( " ", FALSE )))
230        return err;
231
232    /* nested containers
233     * parse an unsorted dict
234     * save as a sorted dict */
235    end = NULL;
236    snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" );
237    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
238    check( !err );
239    check( end == buf + strlen( (const char*)buf ) );
240    check(( child = tr_bencListGetNthChild( &val, 0 )));
241    check(( child2 = tr_bencListGetNthChild( child, 0 )));
242    saved = tr_bencSave( &val, &len );
243    check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) );
244    tr_free( saved );
245    tr_bencFree( &val );
246
247    /* too many endings */
248    end = NULL;
249    snprintf( (char*)buf, sizeof( buf ), "leee" );
250    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
251    check( !err );
252    check( end == buf + 2 );
253    saved = tr_bencSave( &val, &len );
254    check( !strcmp( saved, "le" ) );
255    tr_free( saved );
256    tr_bencFree( &val );
257
258    /* no ending */
259    end = NULL;
260    snprintf( (char*)buf, sizeof( buf ), "l1:a1:b1:c" );
261    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
262    check( err );
263
264    /* incomplete string */
265    end = NULL;
266    snprintf( (char*)buf, sizeof( buf ), "1:" );
267    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
268    check( err );
269
270    return 0;
271}
272
273static int
274testPHPSnippet( const char * benc_str, const char * expected )
275{
276    tr_benc top;
277    char * serialized;
278    tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL );
279    serialized = tr_bencSaveAsSerializedPHP( &top, NULL );
280    check( !strcmp( serialized, expected ) );
281    tr_free( serialized );
282    tr_bencFree( &top );
283    return 0;
284}
285
286static int
287testPHP( void )
288{
289    int val;
290    const char * benc_str;
291    const char * expected;
292
293    benc_str = "i6e";
294    expected = "i:6;";
295    if(( val = testPHPSnippet( benc_str, expected )))
296        return val;
297
298    benc_str = "d3:cow3:moo4:spam4:eggse";
299    expected = "a:2:{s:3:\"cow\";s:3:\"moo\";s:4:\"spam\";s:4:\"eggs\";}";
300    if(( val = testPHPSnippet( benc_str, expected )))
301        return val;
302
303    benc_str = "l3:cow3:moo4:spam4:eggse";
304    expected = "a:4:{i:0;s:3:\"cow\";i:1;s:3:\"moo\";i:2;s:4:\"spam\";i:3;s:4:\"eggs\";}";
305    if(( val = testPHPSnippet( benc_str, expected )))
306        return val;
307
308    return 0;
309}
310
311static int
312testStackSmash( void )
313{
314    int i;
315    int len;
316    int depth;
317    int err;
318    uint8_t * in;
319    const uint8_t * end;
320    tr_benc val;
321    char * saved;
322
323    depth = 1000000;
324    in = tr_new( uint8_t, depth*2 + 1 );
325    for( i=0; i<depth; ++i ) {
326        in[i] = 'l';
327        in[depth+i] = 'e';
328    }
329    in[depth*2] = '\0';
330    err = tr_bencParse( in, in+(depth*2), &val, &end );
331    check( !err );
332    check( end == in+(depth*2) );
333    saved = tr_bencSave( &val, &len );
334    check( !strcmp( saved, (char*)in ) );
335    tr_free( in );
336    tr_free( saved );
337    tr_bencFree( &val );
338
339    return 0;
340}
341
342
343int
344main( void )
345{
346    int i;
347
348    if(( i = testInt( )))
349        return i;
350
351    if(( i = testStr( )))
352        return i;
353
354    if(( i = testParse( )))
355        return i;
356
357    if(( i = testPHP( )))
358        return i;
359
360    if(( i = testStackSmash( )))
361        return i;
362
363    return 0;
364}
Note: See TracBrowser for help on using the repository browser.