~sense/ubuntu/lucid/transmission/fix-497882

« back to all changes in this revision

Viewing changes to libtransmission/bencode-test.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2008-11-28 15:33:48 UTC
  • mfrom: (1.1.19 upstream)
  • Revision ID: james.westby@ubuntu.com-20081128153348-it70trfnxiroblmc
Tags: 1.40-0ubuntu1
* New upstream release (LP: #302672)
  - Tracker communication uses fewer resources
  - More accurate bandwidth limits
  - Reduce disk fragmentation by preallocating files (LP: #287726)
  - Stability, security and performance improvements to the RPC /
    Web UI server (closes LP: #290423)
  - Support compression when serving Web UI and RPC responses
  - Simplify the RPC whitelist
  - Fix bug that prevented handshakes with encrypted BitComet peers
  - Fix 1.3x bug that could re-download some data unnecessarily
    (LP: #295040)
  - Option to automatically update the blocklist weekly
  - Added off-hour bandwidth scheduling
  - Simplify file/priority selection in the details dialog
  - Fix a couple of crashes
  - New / updated translations
  - Don't inhibit hibernation by default (LP: #292929)
  - Use "close" animation when sending to notification area (LP: #130811)
  - Fix resize problems (LP: #269872)
  - Support "--version" option when launching from command line
    (LP: #292011)
  - Correctly parse announce URLs that have leading or trailing
    spaces (LP: #262411)
  - Display an error when "Open Torrent" fails (LP: #281463)
* Dropped 10_fix_crasher_from_upstream.dpatch: Fix is in this
  upstream release.
* debian/control: Don't just build-depend on libcurl-dev, which is
  a virtual package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include <ctype.h>
 
2
#include <errno.h>
2
3
#include <stdio.h>
 
4
#include <string.h>
3
5
#include "transmission.h"
4
6
#include "bencode.h"
5
7
#include "json.h"
9
11
 
10
12
static int test = 0;
11
13
 
12
 
#define check(A) { \
13
 
    ++test; \
14
 
    if (A) { \
15
 
        if( VERBOSE ) \
16
 
            fprintf( stderr, "PASS test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
17
 
    } else { \
18
 
        fprintf( stderr, "FAIL test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
19
 
        return test; \
20
 
    } \
21
 
}
 
14
#define check( A ) \
 
15
    { \
 
16
        ++test; \
 
17
        if( A ){ \
 
18
            if( VERBOSE ) \
 
19
                fprintf( stderr, "PASS test #%d (%s, %d)\n", test, __FILE__,\
 
20
                         __LINE__ );\
 
21
        } else { \
 
22
            fprintf( stderr, "FAIL test #%d (%s, %d)\n", test, __FILE__,\
 
23
                     __LINE__ ); \
 
24
            return test; \
 
25
        } \
 
26
    }
22
27
 
23
28
static int
24
29
testInt( void )
25
30
{
26
 
    uint8_t buf[128];
27
 
    int64_t val;
28
 
    int err;
 
31
    uint8_t         buf[128];
 
32
    int64_t         val;
 
33
    int             err;
29
34
    const uint8_t * end;
30
35
 
31
36
    /* good int string */
32
37
    tr_snprintf( (char*)buf, sizeof( buf ), "i64e" );
33
 
    err = tr_bencParseInt( buf, buf+4, &end, &val );
 
38
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
34
39
    check( err == 0 );
35
40
    check( val == 64 );
36
41
    check( end == buf + 4 );
38
43
    /* missing 'e' */
39
44
    end = NULL;
40
45
    val = 888;
41
 
    err = tr_bencParseInt( buf, buf+3, &end, &val );
42
 
    check( err == TR_ERROR ); 
 
46
    err = tr_bencParseInt( buf, buf + 3, &end, &val );
 
47
    check( err == EILSEQ );
43
48
    check( val == 888 );
44
49
    check( end == NULL );
45
50
 
46
51
    /* empty buffer */
47
 
    err = tr_bencParseInt( buf, buf+0, &end, &val );
48
 
    check( err == TR_ERROR ); 
 
52
    err = tr_bencParseInt( buf, buf + 0, &end, &val );
 
53
    check( err == EILSEQ );
49
54
    check( val == 888 );
50
55
    check( end == NULL );
51
56
 
52
57
    /* bad number */
53
58
    tr_snprintf( (char*)buf, sizeof( buf ), "i6z4e" );
54
 
    err = tr_bencParseInt( buf, buf+5, &end, &val );
55
 
    check( err == TR_ERROR );
 
59
    err = tr_bencParseInt( buf, buf + 5, &end, &val );
 
60
    check( err == EILSEQ );
56
61
    check( val == 888 );
57
62
    check( end == NULL );
58
63
 
59
64
    /* negative number */
60
65
    tr_snprintf( (char*)buf, sizeof( buf ), "i-3e" );
61
 
    err = tr_bencParseInt( buf, buf+4, &end, &val );
62
 
    check( err == TR_OK );
 
66
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
 
67
    check( err == 0 );
63
68
    check( val == -3 );
64
69
    check( end == buf + 4 );
65
70
 
66
71
    /* zero */
67
72
    tr_snprintf( (char*)buf, sizeof( buf ), "i0e" );
68
 
    err = tr_bencParseInt( buf, buf+4, &end, &val );
69
 
    check( err == TR_OK );
 
73
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
 
74
    check( err == 0 );
70
75
    check( val == 0 );
71
76
    check( end == buf + 3 );
72
77
 
74
79
    val = 0;
75
80
    end = NULL;
76
81
    tr_snprintf( (char*)buf, sizeof( buf ), "i04e" );
77
 
    err = tr_bencParseInt( buf, buf+4, &end, &val );
78
 
    check( err == TR_ERROR );
 
82
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
 
83
    check( err == EILSEQ );
79
84
    check( val == 0 );
80
85
    check( end == NULL );
81
86
 
85
90
static int
86
91
testStr( void )
87
92
{
88
 
    uint8_t buf[128];
89
 
    int err;
 
93
    uint8_t         buf[128];
 
94
    int             err;
90
95
    const uint8_t * end;
91
 
    uint8_t * str;
92
 
    size_t len;
 
96
    const uint8_t * str;
 
97
    size_t          len;
93
98
 
94
99
    /* good string */
95
100
    tr_snprintf( (char*)buf, sizeof( buf ), "4:boat" );
96
 
    err = tr_bencParseStr( buf, buf+6, &end, &str, &len );
97
 
    check( err == TR_OK );
98
 
    check( !strcmp( (char*)str, "boat" ) );
 
101
    err = tr_bencParseStr( buf, buf + 6, &end, &str, &len );
 
102
    check( err == 0 );
 
103
    check( !strncmp( (char*)str, "boat", len ) );
99
104
    check( len == 4 );
100
105
    check( end == buf + 6 );
101
 
    tr_free( str );
102
106
    str = NULL;
103
107
    end = NULL;
104
108
    len = 0;
105
109
 
106
110
    /* string goes past end of buffer */
107
 
    err = tr_bencParseStr( buf, buf+5, &end, &str, &len );
108
 
    check( err == TR_ERROR );
 
111
    err = tr_bencParseStr( buf, buf + 5, &end, &str, &len );
 
112
    check( err == EILSEQ );
109
113
    check( str == NULL );
110
114
    check( end == NULL );
111
115
    check( !len );
112
116
 
113
117
    /* empty string */
114
118
    tr_snprintf( (char*)buf, sizeof( buf ), "0:" );
115
 
    err = tr_bencParseStr( buf, buf+2, &end, &str, &len );
116
 
    check( err == TR_OK );
 
119
    err = tr_bencParseStr( buf, buf + 2, &end, &str, &len );
 
120
    check( err == 0 );
117
121
    check( !*str );
118
122
    check( !len );
119
123
    check( end == buf + 2 );
120
 
    tr_free( str );
121
124
    str = NULL;
122
125
    end = NULL;
123
126
    len = 0;
124
127
 
125
128
    /* short string */
126
129
    tr_snprintf( (char*)buf, sizeof( buf ), "3:boat" );
127
 
    err = tr_bencParseStr( buf, buf+6, &end, &str, &len );
128
 
    check( err == TR_OK );
129
 
    check( !strcmp( (char*)str, "boa" ) );
 
130
    err = tr_bencParseStr( buf, buf + 6, &end, &str, &len );
 
131
    check( err == 0 );
 
132
    check( !strncmp( (char*)str, "boa", len ) );
130
133
    check( len == 3 );
131
134
    check( end == buf + 5 );
132
 
    tr_free( str );
133
135
    str = NULL;
134
136
    end = NULL;
135
137
    len = 0;
138
140
}
139
141
 
140
142
static int
141
 
testString( const char * str, int isGood )
 
143
testString( const char * str,
 
144
            int          isGood )
142
145
{
143
 
    tr_benc val;
 
146
    tr_benc         val;
144
147
    const uint8_t * end = NULL;
145
 
    char * saved;
146
 
    const size_t len = strlen( str );
147
 
    int savedLen;
148
 
    int err = tr_bencParse( str, str+len, &val , &end );
149
 
    if( !isGood ) {
 
148
    char *          saved;
 
149
    const size_t    len = strlen( str );
 
150
    int             savedLen;
 
151
    int             err = tr_bencParse( str, str + len, &val, &end );
 
152
 
 
153
    if( !isGood )
 
154
    {
150
155
        check( err );
151
 
    } else {
 
156
    }
 
157
    else
 
158
    {
152
159
        check( !err );
153
160
#if 0
154
161
        fprintf( stderr, "in: [%s]\n", str );
155
 
        fprintf( stderr, "out:\n%s", tr_bencSaveAsJSON(&val,NULL) );
 
162
        fprintf( stderr, "out:\n%s", tr_bencSaveAsJSON( &val, NULL ) );
156
163
#endif
157
164
        check( end == (const uint8_t*)str + len );
158
165
        saved = tr_bencSave( &val, &savedLen );
167
174
static int
168
175
testParse( void )
169
176
{
170
 
    tr_benc val;
171
 
    tr_benc * child;
172
 
    tr_benc * child2;
173
 
    uint8_t buf[512];
 
177
    tr_benc         val;
 
178
    tr_benc *       child;
 
179
    tr_benc *       child2;
 
180
    uint8_t         buf[512];
174
181
    const uint8_t * end;
175
 
    int err;
176
 
    int len;
177
 
    int64_t i;
178
 
    char * saved;
 
182
    int             err;
 
183
    int             len;
 
184
    int64_t         i;
 
185
    char *          saved;
179
186
 
180
187
    tr_snprintf( (char*)buf, sizeof( buf ), "i64e" );
181
188
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
203
210
 
204
211
    end = NULL;
205
212
    tr_snprintf( (char*)buf, sizeof( buf ), "lllee" );
206
 
    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val , &end );
 
213
    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
207
214
    check( err );
208
215
    check( end == NULL );
209
216
 
210
217
    end = NULL;
211
218
    tr_snprintf( (char*)buf, sizeof( buf ), "le" );
212
 
    err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
 
219
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
213
220
    check( !err );
214
221
    check( end == buf + 2 );
215
222
    saved = tr_bencSave( &val, &len );
217
224
    tr_free( saved );
218
225
    tr_bencFree( &val );
219
226
 
220
 
    if(( err = testString( "llleee", TRUE )))
221
 
        return err;
222
 
    if(( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE )))
223
 
        return err;
224
 
    if(( err = testString( "d4:spaml1:a1:bee", TRUE )))
225
 
        return err;
226
 
    if(( err = testString( "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee", TRUE )))
227
 
        return err;
228
 
    if(( err = testString( "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", TRUE )))
229
 
        return err;
230
 
    if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
231
 
        return err;
232
 
    if(( err = testString( "d1:ai0e1:be", FALSE ))) /* odd number of children */
233
 
        return err;
234
 
    if(( err = testString( "", FALSE )))
235
 
        return err;
236
 
    if(( err = testString( " ", FALSE )))
 
227
    if( ( err = testString( "llleee", TRUE ) ) )
 
228
        return err;
 
229
    if( ( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE ) ) )
 
230
        return err;
 
231
    if( ( err = testString( "d4:spaml1:a1:bee", TRUE ) ) )
 
232
        return err;
 
233
    if( ( err =
 
234
             testString( "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee",
 
235
                         TRUE ) ) )
 
236
        return err;
 
237
    if( ( err =
 
238
             testString(
 
239
                 "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee",
 
240
                 TRUE ) ) )
 
241
        return err;
 
242
    if( ( err =
 
243
             testString(
 
244
                 "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e",
 
245
                 TRUE ) ) )
 
246
        return err;
 
247
    if( ( err = testString( "d1:ai0e1:be", FALSE ) ) ) /* odd number of children
 
248
                                                         */
 
249
        return err;
 
250
    if( ( err = testString( "", FALSE ) ) )
 
251
        return err;
 
252
    if( ( err = testString( " ", FALSE ) ) )
237
253
        return err;
238
254
 
239
255
    /* nested containers
244
260
    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
245
261
    check( !err );
246
262
    check( end == buf + strlen( (const char*)buf ) );
247
 
    check(( child = tr_bencListChild( &val, 0 )));
248
 
    check(( child2 = tr_bencListChild( child, 0 )));
 
263
    check( ( child = tr_bencListChild( &val, 0 ) ) );
 
264
    check( ( child2 = tr_bencListChild( child, 0 ) ) );
249
265
    saved = tr_bencSave( &val, &len );
250
266
    check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) );
251
267
    tr_free( saved );
281
297
stripWhitespace( char * in )
282
298
{
283
299
    char * out;
284
 
    for( out=in; *in; ++in )
 
300
 
 
301
    for( out = in; *in; ++in )
285
302
        if( !isspace( *in ) )
286
303
            *out++ = *in;
287
304
    *out = '\0';
288
305
}
289
306
 
290
307
static int
291
 
testJSONSnippet( const char * benc_str, const char * expected )
 
308
testJSONSnippet( const char * benc_str,
 
309
                 const char * expected )
292
310
{
293
311
    tr_benc top;
294
 
    char * serialized;
 
312
    char *  serialized;
 
313
 
295
314
    tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL );
296
315
    serialized = tr_bencSaveAsJSON( &top, NULL );
297
316
    stripWhitespace( serialized );
298
317
#if 0
299
 
fprintf( stderr, "benc: %s\n", benc_str );
300
 
fprintf( stderr, "json: %s\n", serialized );
301
 
fprintf( stderr, "want: %s\n", expected );
 
318
    fprintf( stderr, "benc: %s\n", benc_str );
 
319
    fprintf( stderr, "json: %s\n", serialized );
 
320
    fprintf( stderr, "want: %s\n", expected );
302
321
#endif
303
322
    check( !strcmp( serialized, expected ) );
304
323
    tr_free( serialized );
309
328
static int
310
329
testJSON( void )
311
330
{
312
 
    int val;
 
331
    int          val;
313
332
    const char * benc_str;
314
333
    const char * expected;
315
334
 
316
335
    benc_str = "i6e";
317
336
    expected = "6";
318
 
    if(( val = testJSONSnippet( benc_str, expected )))
 
337
    if( ( val = testJSONSnippet( benc_str, expected ) ) )
319
338
        return val;
320
339
 
321
340
    benc_str = "d5:helloi1e5:worldi2ee";
322
 
    expected = "{\"hello\":1,\"world\":2}"; 
323
 
    if(( val = testJSONSnippet( benc_str, expected )))
 
341
    expected = "{\"hello\":1,\"world\":2}";
 
342
    if( ( val = testJSONSnippet( benc_str, expected ) ) )
324
343
        return val;
325
344
 
326
345
    benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3eee";
327
346
    expected = "{\"foo\":[1,2,3],\"hello\":1,\"world\":2}";
328
 
    if(( val = testJSONSnippet( benc_str, expected )))
 
347
    if( ( val = testJSONSnippet( benc_str, expected ) ) )
329
348
        return val;
330
349
 
331
350
    benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3ed1:ai0eeee";
332
351
    expected = "{\"foo\":[1,2,3,{\"a\":0}],\"hello\":1,\"world\":2}";
333
 
    if(( val = testJSONSnippet( benc_str, expected )))
 
352
    if( ( val = testJSONSnippet( benc_str, expected ) ) )
334
353
        return val;
335
354
 
336
355
    benc_str = "d4:argsd6:statusle7:status2lee6:result7:successe";
337
 
    expected = "{\"args\":{\"status\":[],\"status2\":[]},\"result\":\"success\"}";
338
 
    if(( val = testJSONSnippet( benc_str, expected )))
 
356
    expected =
 
357
        "{\"args\":{\"status\":[],\"status2\":[]},\"result\":\"success\"}";
 
358
    if( ( val = testJSONSnippet( benc_str, expected ) ) )
339
359
        return val;
340
360
 
341
361
    return 0;
342
362
}
343
363
 
344
364
static int
345
 
testStackSmash( void )
 
365
testStackSmash( int depth )
346
366
{
347
 
    int i;
348
 
    int len;
349
 
    int depth;
350
 
    int err;
351
 
    uint8_t * in;
 
367
    int             i;
 
368
    int             len;
 
369
    int             err;
 
370
    uint8_t *       in;
352
371
    const uint8_t * end;
353
 
    tr_benc val;
354
 
    char * saved;
 
372
    tr_benc         val;
 
373
    char *          saved;
355
374
 
356
 
    depth = 1000000;
357
 
    in = tr_new( uint8_t, depth*2 + 1 );
358
 
    for( i=0; i<depth; ++i ) {
 
375
    in = tr_new( uint8_t, depth * 2 + 1 );
 
376
    for( i = 0; i < depth; ++i )
 
377
    {
359
378
        in[i] = 'l';
360
 
        in[depth+i] = 'e';
 
379
        in[depth + i] = 'e';
361
380
    }
362
 
    in[depth*2] = '\0';
363
 
    err = tr_bencParse( in, in+(depth*2), &val, &end );
 
381
    in[depth * 2] = '\0';
 
382
    err = tr_bencParse( in, in + ( depth * 2 ), &val, &end );
364
383
    check( !err );
365
 
    check( end == in+(depth*2) );
 
384
    check( end == in + ( depth * 2 ) );
366
385
    saved = tr_bencSave( &val, &len );
367
386
    check( !strcmp( saved, (char*)in ) );
368
387
    tr_free( in );
372
391
    return 0;
373
392
}
374
393
 
375
 
 
376
394
int
377
395
main( void )
378
396
{
379
397
    int i;
380
398
 
381
 
    if(( i = testInt( )))
382
 
        return i;
383
 
 
384
 
    if(( i = testStr( )))
385
 
        return i;
386
 
 
387
 
    if(( i = testParse( )))
388
 
        return i;
389
 
 
390
 
    if(( i = testJSON( )))
391
 
        return i;
392
 
 
393
 
    if(( i = testStackSmash( )))
 
399
    if( ( i = testInt( ) ) )
 
400
        return i;
 
401
 
 
402
    if( ( i = testStr( ) ) )
 
403
        return i;
 
404
 
 
405
    if( ( i = testParse( ) ) )
 
406
        return i;
 
407
 
 
408
    if( ( i = testJSON( ) ) )
 
409
        return i;
 
410
 
 
411
#ifndef WIN32
 
412
    i = testStackSmash( 1000000 );
 
413
#else
 
414
    i = testStackSmash( 100000 );
 
415
#endif
 
416
    if( i )
394
417
        return i;
395
418
 
396
419
    return 0;
397
420
}
 
421