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

Last change on this file since 5438 was 5438, checked in by charles, 15 years ago

added tr_blocklistGetRuleCount().

  • Property svn:keywords set to Date Rev Author Id
File size: 8.9 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    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(( err = testString( "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", TRUE )))
217        return err;
218    if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
219        return err;
220    if(( err = testString( "d1:ai0e1:be", FALSE ))) /* odd number of children */
221        return err;
222    if(( err = testString( "", FALSE )))
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    /* too many endings */
243    end = NULL;
244    snprintf( (char*)buf, sizeof( buf ), "leee" );
245    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
246    check( !err );
247    check( end == buf + 2 );
248    saved = tr_bencSave( &val, &len );
249    check( !strcmp( saved, "le" ) );
250    tr_free( saved );
251    tr_bencFree( &val );
252
253    /* no ending */
254    end = NULL;
255    snprintf( (char*)buf, sizeof( buf ), "l1:a1:b1:c" );
256    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
257    check( err );
258
259    /* incomplete string */
260    end = NULL;
261    snprintf( (char*)buf, sizeof( buf ), "1:" );
262    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
263    check( err );
264
265    return 0;
266}
267
268static int
269testPHPSnippet( const char * benc_str, const char * expected )
270{
271    tr_benc top;
272    char * serialized;
273    tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL );
274    serialized = tr_bencSaveAsSerializedPHP( &top, NULL );
275    check( !strcmp( serialized, expected ) );
276    tr_free( serialized );
277    tr_bencFree( &top );
278    return 0;
279}
280
281static int
282testPHP( void )
283{
284    int val;
285    const char * benc_str;
286    const char * expected;
287
288    benc_str = "i6e";
289    expected = "i:6;";
290    if(( val = testPHPSnippet( benc_str, expected )))
291        return val;
292
293    benc_str = "d3:cow3:moo4:spam4:eggse";
294    expected = "a:2:{s:3:\"cow\";s:3:\"moo\";s:4:\"spam\";s:4:\"eggs\";}";
295    if(( val = testPHPSnippet( benc_str, expected )))
296        return val;
297
298    benc_str = "l3:cow3:moo4:spam4:eggse";
299    expected = "a:4:{i:0;s:3:\"cow\";i:1;s:3:\"moo\";i:2;s:4:\"spam\";i:3;s:4:\"eggs\";}";
300    if(( val = testPHPSnippet( benc_str, expected )))
301        return val;
302
303    return 0;
304}
305
306static int
307testStackSmash( void )
308{
309    int i;
310    int len;
311    int depth;
312    int err;
313    uint8_t * in;
314    const uint8_t * end;
315    tr_benc val;
316    char * saved;
317
318    depth = 1000000;
319    in = tr_new( uint8_t, depth*2 + 1 );
320    for( i=0; i<depth; ++i ) {
321        in[i] = 'l';
322        in[depth+i] = 'e';
323    }
324    in[depth*2] = '\0';
325    err = tr_bencParse( in, in+(depth*2), &val, &end );
326    check( !err );
327    check( end == in+(depth*2) );
328    saved = tr_bencSave( &val, &len );
329    check( !strcmp( saved, (char*)in ) );
330    tr_free( in );
331    tr_free( saved );
332    tr_bencFree( &val );
333
334    return 0;
335}
336
337
338int
339main( void )
340{
341    int i;
342
343    if(( i = testInt( )))
344        return i;
345
346    if(( i = testStr( )))
347        return i;
348
349    if(( i = testParse( )))
350        return i;
351
352    if(( i = testPHP( )))
353        return i;
354
355    if(( i = testStackSmash( )))
356        return i;
357
358    return 0;
359}
Note: See TracBrowser for help on using the repository browser.