source: trunk/libtransmission/utils-test.c @ 12918

Last change on this file since 12918 was 12324, checked in by jordan, 11 years ago

(trunk libT) fix ABR error when parsing a URL with no path and no trailing slash after the host. Error reported by livings124

File size: 13.3 KB
Line 
1#include <math.h>
2#include <stdio.h> /* fprintf */
3#include <string.h> /* strcmp */
4
5#include "transmission.h"
6#include "bitfield.h"
7#include "ConvertUTF.h" /* tr_utf8_validate*/
8#include "platform.h"
9#include "crypto.h"
10#include "utils.h"
11#include "web.h"
12
13/* #define VERBOSE */
14#undef VERBOSE
15#define NUM_LOOPS 1
16#define SPEED_TEST 0
17
18#if SPEED_TEST
19 #define VERBOSE
20 #undef NUM_LOOPS
21 #define NUM_LOOPS 200
22#endif
23
24static int test = 0;
25
26#ifdef VERBOSE
27  #define check( A ) \
28    { \
29        ++test; \
30        if( A ){ \
31            fprintf( stderr, "PASS test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
32        } else { \
33            fprintf( stderr, "FAIL test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
34            return test; \
35        } \
36    }
37#else
38  #define check( A ) \
39    { \
40        ++test; \
41        if( !( A ) ){ \
42            fprintf( stderr, "FAIL test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
43            return test; \
44        } \
45    }
46#endif
47
48static int
49test_bitfield_count_range( void )
50{
51    int i;
52    int n;
53    int begin;
54    int end;
55    int count1;
56    int count2;
57    const int bitCount = 100 + tr_cryptoWeakRandInt( 1000 );
58    tr_bitfield bf;
59
60    /* generate a random bitfield */
61    tr_bitfieldConstruct( &bf, bitCount );
62    for( i=0, n=tr_cryptoWeakRandInt(bitCount); i<n; ++i )
63        tr_bitfieldAdd( &bf, tr_cryptoWeakRandInt(bitCount) );
64
65    begin = tr_cryptoWeakRandInt( bitCount );
66    do {
67        end = tr_cryptoWeakRandInt( bitCount );
68    } while( end == begin );
69    if( end < begin ) {
70        const int tmp = begin;
71        begin = end;
72        end = tmp;
73    }
74
75    count1 = 0;
76    for( i=begin; i<end; ++i )
77        if( tr_bitfieldHas( &bf, i ) )
78            ++count1;
79    count2 = tr_bitfieldCountRange( &bf, begin, end );
80    check( count1 == count2 );
81
82    tr_bitfieldDestruct( &bf );
83    return 0;
84}
85
86static int
87test_bitfields( void )
88{
89    unsigned int  i;
90    unsigned int  bitcount = 500;
91    tr_bitfield field;
92
93    tr_bitfieldConstruct( &field, bitcount );
94
95    /* test tr_bitfieldAdd */
96    for( i = 0; i < bitcount; ++i )
97        if( !( i % 7 ) )
98            tr_bitfieldAdd( &field, i );
99    for( i = 0; i < bitcount; ++i )
100        check( tr_bitfieldHas( &field, i ) == ( !( i % 7 ) ) );
101
102    /* test tr_bitfieldAddRange */
103    tr_bitfieldAddRange( &field, 0, bitcount );
104    for( i = 0; i < bitcount; ++i )
105        check( tr_bitfieldHas( &field, i ) );
106
107    /* test tr_bitfieldRemRange in the middle of a boundary */
108    tr_bitfieldRemRange( &field, 4, 21 );
109    for( i = 0; i < 64; ++i )
110        check( tr_bitfieldHas( &field, i ) == ( ( i < 4 ) || ( i >= 21 ) ) );
111
112    /* test tr_bitfieldRemRange on the boundaries */
113    tr_bitfieldAddRange( &field, 0, 64 );
114    tr_bitfieldRemRange( &field, 8, 24 );
115    for( i = 0; i < 64; ++i )
116        check( tr_bitfieldHas( &field, i ) == ( ( i < 8 ) || ( i >= 24 ) ) );
117
118    /* test tr_bitfieldRemRange when begin & end is on the same word */
119    tr_bitfieldAddRange( &field, 0, 64 );
120    tr_bitfieldRemRange( &field, 4, 5 );
121    for( i = 0; i < 64; ++i )
122        check( tr_bitfieldHas( &field, i ) == ( ( i < 4 ) || ( i >= 5 ) ) );
123
124    /* test tr_bitfieldAddRange */
125    tr_bitfieldRemRange( &field, 0, 64 );
126    tr_bitfieldAddRange( &field, 4, 21 );
127    for( i = 0; i < 64; ++i )
128        check( tr_bitfieldHas( &field, i ) == ( ( 4 <= i ) && ( i < 21 ) ) );
129
130    /* test tr_bitfieldAddRange on the boundaries */
131    tr_bitfieldRemRange( &field, 0, 64 );
132    tr_bitfieldAddRange( &field, 8, 24 );
133    for( i = 0; i < 64; ++i )
134        check( tr_bitfieldHas( &field, i ) == ( ( 8 <= i ) && ( i < 24 ) ) );
135
136    /* test tr_bitfieldAddRange when begin & end is on the same word */
137    tr_bitfieldRemRange( &field, 0, 64 );
138    tr_bitfieldAddRange( &field, 4, 5 );
139    for( i = 0; i < 64; ++i )
140        check( tr_bitfieldHas( &field, i ) == ( ( 4 <= i ) && ( i < 5 ) ) );
141
142    tr_bitfieldDestruct( &field );
143    return 0;
144}
145
146static int
147test_strip_positional_args( void )
148{
149    const char * in;
150    const char * out;
151    const char * expected;
152
153    in = "Hello %1$s foo %2$.*f";
154    expected = "Hello %s foo %.*f";
155    out = tr_strip_positional_args( in );
156    check( out != NULL )
157    check( !strcmp( out, expected ) )
158
159    in = "Hello %1$'d foo %2$'f";
160    expected = "Hello %d foo %f";
161    out = tr_strip_positional_args( in );
162    check( out != NULL )
163    check( !strcmp( out, expected ) )
164
165    return 0;
166}
167
168static int
169test_strstrip( void )
170{
171    char *in, *out;
172
173    /* strstrip */
174    in = tr_strdup( "   test    " );
175    out = tr_strstrip( in );
176    check( in == out );
177    check( !strcmp( in, "test" ) );
178    tr_free( in );
179
180    /* strstrip */
181    in = tr_strdup( " test test " );
182    out = tr_strstrip( in );
183    check( in == out );
184    check( !strcmp( in, "test test" ) );
185    tr_free( in );
186
187    /* strstrip */
188    in = tr_strdup( "test" );
189    out = tr_strstrip( in );
190    check( in == out );
191    check( !strcmp( in, "test" ) );
192    tr_free( in );
193
194    return 0;
195}
196
197static int
198test_buildpath( void )
199{
200    char * out;
201
202    out = tr_buildPath( "foo", "bar", NULL );
203    check( !strcmp( out, "foo" TR_PATH_DELIMITER_STR "bar" ) );
204    tr_free( out );
205
206    out = tr_buildPath( "", "foo", "bar", NULL );
207    check( !strcmp( out, TR_PATH_DELIMITER_STR "foo" TR_PATH_DELIMITER_STR "bar" ) );
208    tr_free( out );
209
210    return 0;
211}
212
213static int
214test_utf8( void )
215{
216    const char * in;
217    char * out;
218
219    in = "hello world";
220    out = tr_utf8clean( in, -1 );
221    check( out != NULL )
222    check( !strcmp( out, in ) )
223    tr_free( out );
224
225    in = "hello world";
226    out = tr_utf8clean( in, 5 );
227    check( out != NULL )
228    check( !strcmp( out, "hello" ) )
229    tr_free( out );
230
231    /* this version is not utf-8 */
232    in = "Òðóäíî áûòü Áîãîì";
233    out = tr_utf8clean( in, 17 );
234    check( out != NULL )
235    check( ( strlen( out ) == 17 ) || ( strlen( out ) == 32 ) )
236    check( tr_utf8_validate( out, -1, NULL ) )
237    tr_free( out );
238
239    /* same string, but utf-8 clean */
240    in = "ÒðóÀíî áûòÌ Áîãîì";
241    out = tr_utf8clean( in, -1 );
242    check( out != NULL )
243    check( tr_utf8_validate( out, -1, NULL ) )
244    check ( !strcmp( in, out ) )
245    tr_free( out );
246
247    return 0;
248}
249
250static int
251test_numbers( void )
252{
253    int i;
254    int count;
255    int * numbers;
256
257    numbers = tr_parseNumberRange( "1-10,13,16-19", -1, &count );
258    check( count == 15 );
259    check( numbers != NULL );
260    check( numbers[0] == 1 );
261    check( numbers[5] == 6 );
262    check( numbers[9] == 10 );
263    check( numbers[10] == 13 );
264    check( numbers[11] == 16 );
265    check( numbers[14] == 19 );
266    tr_free( numbers );
267
268    numbers = tr_parseNumberRange( "1-5,3-7,2-6", -1, &count );
269    check( count == 7 );
270    check( numbers != NULL );
271    for( i=0; i<count; ++i )
272        check( numbers[i] == i+1 );
273    tr_free( numbers );
274
275    numbers = tr_parseNumberRange( "1-Hello", -1, &count );
276    check( count == 0 );
277    check( numbers == NULL );
278
279    numbers = tr_parseNumberRange( "1-", -1, &count );
280    check( count == 0 );
281    check( numbers == NULL );
282
283    numbers = tr_parseNumberRange( "Hello", -1, &count );
284    check( count == 0 );
285    check( numbers == NULL );
286
287    return 0;
288}
289
290static int
291compareInts( const void * va, const void * vb )
292{
293    const int a = *(const int *)va;
294    const int b = *(const int*)vb;
295    return a - b;
296}
297
298static int
299test_lowerbound( void )
300{
301    int i;
302    const int A[] = { 1, 2, 3, 3, 3, 5, 8 };
303    const int expected_pos[] = { 0, 1, 2, 5, 5, 6, 6, 6, 7, 7 };
304    const int expected_exact[] = { true, true, true, false, true, false, false, true, false, false };
305    const int N = sizeof(A) / sizeof(A[0]);
306
307    for( i=1; i<=10; ++i )
308    {
309        bool exact;
310        const int pos = tr_lowerBound( &i, A, N, sizeof(int), compareInts, &exact );
311
312#if 0
313        fprintf( stderr, "searching for %d. ", i );
314        fprintf( stderr, "result: index = %d, ", pos );
315        if( pos != N )
316            fprintf( stderr, "A[%d] == %d\n", pos, A[pos] );
317        else
318            fprintf( stderr, "which is off the end.\n" );
319#endif
320        check( pos == expected_pos[i-1] )
321        check( exact == expected_exact[i-1] )
322    }
323
324    return 0;
325}
326
327static int
328test_memmem( void )
329{
330    char const haystack[12] = "abcabcabcabc";
331    char const needle[3] = "cab";
332
333    check( tr_memmem( haystack, sizeof haystack, haystack, sizeof haystack) == haystack )
334    check( tr_memmem( haystack, sizeof haystack, needle, sizeof needle) == haystack + 2 )
335    check( tr_memmem( needle, sizeof needle, haystack, sizeof haystack) == NULL )
336
337    return 0;
338}
339
340static int
341test_hex( void )
342{
343    char hex1[41];
344    char hex2[41];
345    uint8_t sha1[20];
346    /*uint8_t sha2[20];*/
347
348    memcpy( hex1, "fb5ef5507427b17e04b69cef31fa3379b456735a", 41 );
349    tr_hex_to_sha1( sha1, hex1 );
350    tr_sha1_to_hex( hex2, sha1 );
351    check( !strcmp( hex1, hex2 ) )
352
353    return 0;
354}
355
356static int
357test_array( void )
358{
359    int i;
360    int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
361    int n = sizeof( array ) / sizeof( array[0] );
362
363    tr_removeElementFromArray( array, 5u, sizeof( int ), n-- );
364    for( i=0; i<n; ++i )
365        check( array[i] == ( i<5 ? i : i+1 ) );
366
367    tr_removeElementFromArray( array, 0u, sizeof( int ), n-- );
368    for( i=0; i<n; ++i )
369        check( array[i] == ( i<4 ? i+1 : i+2 ) );
370
371    tr_removeElementFromArray( array, n-1, sizeof( int ), n ); n--;
372    for( i=0; i<n; ++i )
373        check( array[i] == ( i<4 ? i+1 : i+2 ) );
374
375    return 0;
376}
377
378static int
379test_url( void )
380{
381    int port;
382    char * scheme;
383    char * host;
384    char * path;
385    char * str;
386    const char * url;
387
388    url = "http://1";
389    check( !tr_urlParse( url, -1, &scheme, &host, &port, &path ) );
390    check( !strcmp( scheme, "http" ) )
391    check( !strcmp( host, "1" ) )
392    check( !strcmp( path, "/" ) )
393    check( port == 80 )
394    tr_free( scheme );
395    tr_free( path );
396    tr_free( host );
397
398    url = "http://www.some-tracker.org/some/path";
399    check( !tr_urlParse( url, -1, &scheme, &host, &port, &path ) )
400    check( !strcmp( scheme, "http" ) )
401    check( !strcmp( host, "www.some-tracker.org" ) )
402    check( !strcmp( path, "/some/path" ) )
403    check( port == 80 )
404    tr_free( scheme );
405    tr_free( path );
406    tr_free( host );
407
408    url = "http://www.some-tracker.org:80/some/path";
409    check( !tr_urlParse( url, -1, &scheme, &host, &port, &path ) )
410    check( !strcmp( scheme, "http" ) )
411    check( !strcmp( host, "www.some-tracker.org" ) )
412    check( !strcmp( path, "/some/path" ) )
413    check( port == 80 )
414    tr_free( scheme );
415    tr_free( path );
416    tr_free( host );
417
418    url = "http%3A%2F%2Fwww.example.com%2F~user%2F%3Ftest%3D1%26test1%3D2";
419    str = tr_http_unescape( url, strlen( url ) );
420    check( !strcmp( str, "http://www.example.com/~user/?test=1&test1=2" ) )
421    tr_free( str );
422
423    return 0;
424}
425
426static int
427test_truncd( void )
428{
429    char buf[32];
430    const double nan = sqrt( -1 );
431
432    tr_snprintf( buf, sizeof( buf ), "%.2f%%", 99.999 );
433    check( !strcmp( buf, "100.00%" ) );
434
435    tr_snprintf( buf, sizeof( buf ), "%.2f%%", tr_truncd( 99.999, 2 ) );
436    check( !strcmp( buf, "99.99%" ) );
437
438    tr_snprintf( buf, sizeof( buf ), "%.4f", tr_truncd( 403650.656250, 4 ) );
439    check( !strcmp( buf, "403650.6562" ) );
440
441    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 2.15, 2 ) );
442    check( !strcmp( buf, "2.15" ) );
443
444    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 2.05, 2 ) );
445    check( !strcmp( buf, "2.05" ) );
446
447    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 3.3333, 2 ) );
448    check( !strcmp( buf, "3.33" ) );
449
450    tr_snprintf( buf, sizeof( buf ), "%.0f", tr_truncd( 3.3333, 0 ) );
451    check( !strcmp( buf, "3" ) );
452
453    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( nan, 2 ) );
454    check( strstr( buf, "nan" ) != NULL );
455
456    return 0;
457}
458
459struct blah
460{
461    uint8_t  hash[SHA_DIGEST_LENGTH];  /* pieces hash */
462    int8_t   priority;                 /* TR_PRI_HIGH, _NORMAL, or _LOW */
463    int8_t   dnd;                      /* "do not download" flag */
464    time_t   timeChecked;              /* the last time we tested this piece */
465};
466
467
468int
469main( void )
470{
471    char *in, *out;
472    int   len;
473    int   i;
474    int   l;
475
476    /* base64 */
477    out = tr_base64_encode( "YOYO!", -1, &len );
478    check( out );
479    check( !strcmp( out, "WU9ZTyE=" ) );
480    check( len == 8 );
481    in = tr_base64_decode( out, -1, &len );
482    check( in );
483    check( !strcmp( in, "YOYO!" ) );
484    check( len == 5 );
485    tr_free( in );
486    tr_free( out );
487    out = tr_base64_encode( NULL, 0, &len );
488    check( out == NULL );
489    check( len == 0 );
490
491    if( ( i = test_hex( ) ) )
492        return i;
493    if( ( i = test_lowerbound( ) ) )
494        return i;
495    if( ( i = test_strip_positional_args( ) ) )
496        return i;
497    if( ( i = test_strstrip( ) ) )
498        return i;
499    if( ( i = test_buildpath( ) ) )
500        return i;
501    if( ( i = test_utf8( ) ) )
502        return i;
503    if( ( i = test_numbers( ) ) )
504        return i;
505    if( ( i = test_memmem( ) ) )
506        return i;
507    if( ( i = test_array( ) ) )
508        return i;
509    if( ( i = test_url( ) ) )
510        return i;
511    if( ( i = test_truncd( ) ) )
512        return i;
513
514    /* test that tr_cryptoRandInt() stays in-bounds */
515    for( i = 0; i < 100000; ++i )
516    {
517        const int val = tr_cryptoRandInt( 100 );
518        check( val >= 0 );
519        check( val < 100 );
520    }
521
522    /* simple bitfield tests */
523    for( l = 0; l < NUM_LOOPS; ++l )
524        if( ( i = test_bitfields( ) ) )
525            return i;
526
527    /* bitfield count range */
528    for( l=0; l<10000; ++l )
529        if(( i = test_bitfield_count_range( )))
530            return i;
531
532    return 0;
533}
534
Note: See TracBrowser for help on using the repository browser.