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

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

(trunk libT) break the mac build and introduce new crashes.

This is partially to address #4145 "Downloads stuck at 100%" by refactoring the bitset, bitfield, and tr_completion; however, the ripple effect is larger than usual so things may get worse in the short term before getting better.

livings124: to fix the mac build, remove bitset.[ch] from xcode

File size: 13.0 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://www.some-tracker.org/some/path";
389    check( !tr_urlParse( url, -1, &scheme, &host, &port, &path ) )
390    check( !strcmp( scheme, "http" ) )
391    check( !strcmp( host, "www.some-tracker.org" ) )
392    check( !strcmp( path, "/some/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:80/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%3A%2F%2Fwww.example.com%2F~user%2F%3Ftest%3D1%26test1%3D2";
409    str = tr_http_unescape( url, strlen( url ) );
410    check( !strcmp( str, "http://www.example.com/~user/?test=1&test1=2" ) )
411    tr_free( str );
412
413    return 0;
414}
415
416static int
417test_truncd( void )
418{
419    char buf[32];
420    const double nan = sqrt( -1 );
421
422    tr_snprintf( buf, sizeof( buf ), "%.2f%%", 99.999 );
423    check( !strcmp( buf, "100.00%" ) );
424
425    tr_snprintf( buf, sizeof( buf ), "%.2f%%", tr_truncd( 99.999, 2 ) );
426    check( !strcmp( buf, "99.99%" ) );
427
428    tr_snprintf( buf, sizeof( buf ), "%.4f", tr_truncd( 403650.656250, 4 ) );
429    check( !strcmp( buf, "403650.6562" ) );
430
431    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 2.15, 2 ) );
432    check( !strcmp( buf, "2.15" ) );
433
434    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 2.05, 2 ) );
435    check( !strcmp( buf, "2.05" ) );
436
437    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 3.3333, 2 ) );
438    check( !strcmp( buf, "3.33" ) );
439
440    tr_snprintf( buf, sizeof( buf ), "%.0f", tr_truncd( 3.3333, 0 ) );
441    check( !strcmp( buf, "3" ) );
442
443    tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( nan, 2 ) );
444    check( strstr( buf, "nan" ) != NULL );
445
446    return 0;
447}
448
449struct blah
450{
451    uint8_t  hash[SHA_DIGEST_LENGTH];  /* pieces hash */
452    int8_t   priority;                 /* TR_PRI_HIGH, _NORMAL, or _LOW */
453    int8_t   dnd;                      /* "do not download" flag */
454    time_t   timeChecked;              /* the last time we tested this piece */
455};
456
457
458int
459main( void )
460{
461    char *in, *out;
462    int   len;
463    int   i;
464    int   l;
465
466    /* base64 */
467    out = tr_base64_encode( "YOYO!", -1, &len );
468    check( out );
469    check( !strcmp( out, "WU9ZTyE=" ) );
470    check( len == 8 );
471    in = tr_base64_decode( out, -1, &len );
472    check( in );
473    check( !strcmp( in, "YOYO!" ) );
474    check( len == 5 );
475    tr_free( in );
476    tr_free( out );
477    out = tr_base64_encode( NULL, 0, &len );
478    check( out == NULL );
479    check( len == 0 );
480
481    if( ( i = test_hex( ) ) )
482        return i;
483    if( ( i = test_lowerbound( ) ) )
484        return i;
485    if( ( i = test_strip_positional_args( ) ) )
486        return i;
487    if( ( i = test_strstrip( ) ) )
488        return i;
489    if( ( i = test_buildpath( ) ) )
490        return i;
491    if( ( i = test_utf8( ) ) )
492        return i;
493    if( ( i = test_numbers( ) ) )
494        return i;
495    if( ( i = test_memmem( ) ) )
496        return i;
497    if( ( i = test_array( ) ) )
498        return i;
499    if( ( i = test_url( ) ) )
500        return i;
501    if( ( i = test_truncd( ) ) )
502        return i;
503
504    /* test that tr_cryptoRandInt() stays in-bounds */
505    for( i = 0; i < 100000; ++i )
506    {
507        const int val = tr_cryptoRandInt( 100 );
508        check( val >= 0 );
509        check( val < 100 );
510    }
511
512    /* simple bitfield tests */
513    for( l = 0; l < NUM_LOOPS; ++l )
514        if( ( i = test_bitfields( ) ) )
515            return i;
516
517    /* bitfield count range */
518    for( l=0; l<10000; ++l )
519        if(( i = test_bitfield_count_range( )))
520            return i;
521
522    return 0;
523}
524
Note: See TracBrowser for help on using the repository browser.