Revert "transmission: update from 2.13 to 2.22"
[tomato.git] / release / src / router / transmission / libtransmission / utils-test.c
blobc07d2fe64e94ada024e53d777f78ce920490e5b5
1 #include <math.h>
2 #include <stdio.h> /* fprintf */
3 #include <string.h> /* strcmp */
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"
13 /* #define VERBOSE */
14 #undef VERBOSE
15 #define NUM_LOOPS 1
16 #define SPEED_TEST 0
18 #if SPEED_TEST
19 #define VERBOSE
20 #undef NUM_LOOPS
21 #define NUM_LOOPS 200
22 #endif
24 static int test = 0;
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 } \
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 } \
46 #endif
48 static int
49 test_bitfields( void )
51 unsigned int i;
52 unsigned int bitcount = 5000000;
53 tr_bitfield * field = tr_bitfieldNew( bitcount );
55 /* test tr_bitfieldAdd */
56 for( i = 0; i < bitcount; ++i )
57 if( !( i % 7 ) )
58 tr_bitfieldAdd( field, i );
59 for( i = 0; i < bitcount; ++i )
60 check( tr_bitfieldHas( field, i ) == ( !( i % 7 ) ) );
62 /* test tr_bitfieldAddRange */
63 tr_bitfieldAddRange( field, 0, bitcount );
64 for( i = 0; i < bitcount; ++i )
65 check( tr_bitfieldHas( field, i ) );
67 /* test tr_bitfieldRemRange in the middle of a boundary */
68 tr_bitfieldRemRange( field, 4, 21 );
69 for( i = 0; i < 64; ++i )
70 check( tr_bitfieldHas( field, i ) == ( ( i < 4 ) || ( i >= 21 ) ) );
72 /* test tr_bitfieldRemRange on the boundaries */
73 tr_bitfieldAddRange( field, 0, 64 );
74 tr_bitfieldRemRange( field, 8, 24 );
75 for( i = 0; i < 64; ++i )
76 check( tr_bitfieldHas( field, i ) == ( ( i < 8 ) || ( i >= 24 ) ) );
78 /* test tr_bitfieldRemRange when begin & end is on the same word */
79 tr_bitfieldAddRange( field, 0, 64 );
80 tr_bitfieldRemRange( field, 4, 5 );
81 for( i = 0; i < 64; ++i )
82 check( tr_bitfieldHas( field, i ) == ( ( i < 4 ) || ( i >= 5 ) ) );
84 /* test tr_bitfieldAddRange */
85 tr_bitfieldRemRange( field, 0, 64 );
86 tr_bitfieldAddRange( field, 4, 21 );
87 for( i = 0; i < 64; ++i )
88 check( tr_bitfieldHas( field, i ) == ( ( 4 <= i ) && ( i < 21 ) ) );
90 /* test tr_bitfieldAddRange on the boundaries */
91 tr_bitfieldRemRange( field, 0, 64 );
92 tr_bitfieldAddRange( field, 8, 24 );
93 for( i = 0; i < 64; ++i )
94 check( tr_bitfieldHas( field, i ) == ( ( 8 <= i ) && ( i < 24 ) ) );
96 /* test tr_bitfieldAddRange when begin & end is on the same word */
97 tr_bitfieldRemRange( field, 0, 64 );
98 tr_bitfieldAddRange( field, 4, 5 );
99 for( i = 0; i < 64; ++i )
100 check( tr_bitfieldHas( field, i ) == ( ( 4 <= i ) && ( i < 5 ) ) );
102 tr_bitfieldFree( field );
103 return 0;
106 static int
107 test_strip_positional_args( void )
109 const char * in;
110 const char * out;
111 const char * expected;
113 in = "Hello %1$s foo %2$.*f";
114 expected = "Hello %s foo %.*f";
115 out = tr_strip_positional_args( in );
116 check( out != NULL )
117 check( !strcmp( out, expected ) )
119 in = "Hello %1$'d foo %2$'f";
120 expected = "Hello %d foo %f";
121 out = tr_strip_positional_args( in );
122 check( out != NULL )
123 check( !strcmp( out, expected ) )
125 return 0;
128 static int
129 test_strstrip( void )
131 char *in, *out;
133 /* strstrip */
134 in = tr_strdup( " test " );
135 out = tr_strstrip( in );
136 check( in == out );
137 check( !strcmp( in, "test" ) );
138 tr_free( in );
140 /* strstrip */
141 in = tr_strdup( " test test " );
142 out = tr_strstrip( in );
143 check( in == out );
144 check( !strcmp( in, "test test" ) );
145 tr_free( in );
147 /* strstrip */
148 in = tr_strdup( "test" );
149 out = tr_strstrip( in );
150 check( in == out );
151 check( !strcmp( in, "test" ) );
152 tr_free( in );
154 return 0;
157 static int
158 test_buildpath( void )
160 char * out;
162 out = tr_buildPath( "foo", "bar", NULL );
163 check( !strcmp( out, "foo" TR_PATH_DELIMITER_STR "bar" ) );
164 tr_free( out );
166 out = tr_buildPath( "", "foo", "bar", NULL );
167 check( !strcmp( out, TR_PATH_DELIMITER_STR "foo" TR_PATH_DELIMITER_STR "bar" ) );
168 tr_free( out );
170 return 0;
173 static int
174 test_utf8( void )
176 const char * in;
177 char * out;
179 in = "hello world";
180 out = tr_utf8clean( in, -1 );
181 check( out != NULL )
182 check( !strcmp( out, in ) )
183 tr_free( out );
185 in = "hello world";
186 out = tr_utf8clean( in, 5 );
187 check( out != NULL )
188 check( !strcmp( out, "hello" ) )
189 tr_free( out );
191 /* this version is not utf-8 */
192 in = "Òðóäíî áûòü Áîãîì";
193 out = tr_utf8clean( in, 17 );
194 check( out != NULL )
195 check( ( strlen( out ) == 17 ) || ( strlen( out ) == 32 ) )
196 check( tr_utf8_validate( out, -1, NULL ) )
197 tr_free( out );
199 /* same string, but utf-8 clean */
200 in = "Òðóäíî áûòü Áîãîì";
201 out = tr_utf8clean( in, -1 );
202 check( out != NULL )
203 check( tr_utf8_validate( out, -1, NULL ) )
204 check ( !strcmp( in, out ) )
205 tr_free( out );
207 return 0;
210 static int
211 test_numbers( void )
213 int i;
214 int count;
215 int * numbers;
217 numbers = tr_parseNumberRange( "1-10,13,16-19", -1, &count );
218 check( count == 15 );
219 check( numbers != NULL );
220 check( numbers[0] == 1 );
221 check( numbers[5] == 6 );
222 check( numbers[9] == 10 );
223 check( numbers[10] == 13 );
224 check( numbers[11] == 16 );
225 check( numbers[14] == 19 );
226 tr_free( numbers );
228 numbers = tr_parseNumberRange( "1-5,3-7,2-6", -1, &count );
229 check( count == 7 );
230 check( numbers != NULL );
231 for( i=0; i<count; ++i )
232 check( numbers[i] == i+1 );
233 tr_free( numbers );
235 numbers = tr_parseNumberRange( "1-Hello", -1, &count );
236 check( count == 0 );
237 check( numbers == NULL );
239 numbers = tr_parseNumberRange( "1-", -1, &count );
240 check( count == 0 );
241 check( numbers == NULL );
243 numbers = tr_parseNumberRange( "Hello", -1, &count );
244 check( count == 0 );
245 check( numbers == NULL );
247 return 0;
250 static int
251 compareInts( const void * va, const void * vb )
253 const int a = *(const int *)va;
254 const int b = *(const int*)vb;
255 return a - b;
258 static int
259 test_lowerbound( void )
261 int i;
262 const int A[] = { 1, 2, 3, 3, 3, 5, 8 };
263 const int expected_pos[] = { 0, 1, 2, 5, 5, 6, 6, 6, 7, 7 };
264 const int expected_exact[] = { TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE };
265 const int N = sizeof(A) / sizeof(A[0]);
267 for( i=1; i<=10; ++i )
269 tr_bool exact;
270 const int pos = tr_lowerBound( &i, A, N, sizeof(int), compareInts, &exact );
272 #if 0
273 fprintf( stderr, "searching for %d. ", i );
274 fprintf( stderr, "result: index = %d, ", pos );
275 if( pos != N )
276 fprintf( stderr, "A[%d] == %d\n", pos, A[pos] );
277 else
278 fprintf( stderr, "which is off the end.\n" );
279 #endif
280 check( pos == expected_pos[i-1] )
281 check( exact == expected_exact[i-1] )
284 return 0;
287 static int
288 test_memmem( void )
290 char const haystack[12] = "abcabcabcabc";
291 char const needle[3] = "cab";
293 check( tr_memmem( haystack, sizeof haystack, haystack, sizeof haystack) == haystack )
294 check( tr_memmem( haystack, sizeof haystack, needle, sizeof needle) == haystack + 2 )
295 check( tr_memmem( needle, sizeof needle, haystack, sizeof haystack) == NULL )
296 check( tr_memmem( haystack, sizeof haystack, "", 0) == haystack )
297 check( tr_memmem( haystack, sizeof haystack, NULL, 0) == haystack )
298 check( tr_memmem( haystack, 0, "", 0) == haystack )
300 return 0;
303 static int
304 test_hex( void )
306 char hex1[41];
307 char hex2[41];
308 uint8_t sha1[20];
309 /*uint8_t sha2[20];*/
311 memcpy( hex1, "fb5ef5507427b17e04b69cef31fa3379b456735a", 41 );
312 tr_hex_to_sha1( sha1, hex1 );
313 tr_sha1_to_hex( hex2, sha1 );
314 check( !strcmp( hex1, hex2 ) )
316 return 0;
319 static int
320 test_array( void )
322 int i;
323 int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
324 int n = sizeof( array ) / sizeof( array[0] );
326 tr_removeElementFromArray( array, 5u, sizeof( int ), n-- );
327 for( i=0; i<n; ++i )
328 check( array[i] == ( i<5 ? i : i+1 ) );
330 tr_removeElementFromArray( array, 0u, sizeof( int ), n-- );
331 for( i=0; i<n; ++i )
332 check( array[i] == ( i<4 ? i+1 : i+2 ) );
334 tr_removeElementFromArray( array, n-1, sizeof( int ), n ); n--;
335 for( i=0; i<n; ++i )
336 check( array[i] == ( i<4 ? i+1 : i+2 ) );
338 return 0;
341 static int
342 test_url( void )
344 int port;
345 char * scheme;
346 char * host;
347 char * path;
348 char * str;
349 const char * url;
351 url = "http://www.some-tracker.org/some/path";
352 check( !tr_urlParse( url, -1, &scheme, &host, &port, &path ) )
353 check( !strcmp( scheme, "http" ) )
354 check( !strcmp( host, "www.some-tracker.org" ) )
355 check( !strcmp( path, "/some/path" ) )
356 check( port == 80 )
357 tr_free( scheme );
358 tr_free( path );
359 tr_free( host );
361 url = "http://www.some-tracker.org:80/some/path";
362 check( !tr_urlParse( url, -1, &scheme, &host, &port, &path ) )
363 check( !strcmp( scheme, "http" ) )
364 check( !strcmp( host, "www.some-tracker.org" ) )
365 check( !strcmp( path, "/some/path" ) )
366 check( port == 80 )
367 tr_free( scheme );
368 tr_free( path );
369 tr_free( host );
371 url = "http%3A%2F%2Fwww.example.com%2F~user%2F%3Ftest%3D1%26test1%3D2";
372 str = tr_http_unescape( url, strlen( url ) );
373 check( !strcmp( str, "http://www.example.com/~user/?test=1&test1=2" ) )
374 tr_free( str );
376 return 0;
379 static int
380 test_truncd( void )
382 char buf[32];
383 const double nan = sqrt( -1 );
385 tr_snprintf( buf, sizeof( buf ), "%.2f%%", 99.999 );
386 check( !strcmp( buf, "100.00%" ) );
388 tr_snprintf( buf, sizeof( buf ), "%.2f%%", tr_truncd( 99.999, 2 ) );
389 check( !strcmp( buf, "99.99%" ) );
391 tr_snprintf( buf, sizeof( buf ), "%.4f", tr_truncd( 403650.656250, 4 ) );
392 check( !strcmp( buf, "403650.6562" ) );
394 tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 2.15, 2 ) );
395 check( !strcmp( buf, "2.15" ) );
397 tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 2.05, 2 ) );
398 check( !strcmp( buf, "2.05" ) );
400 tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( 3.3333, 2 ) );
401 check( !strcmp( buf, "3.33" ) );
403 tr_snprintf( buf, sizeof( buf ), "%.0f", tr_truncd( 3.3333, 0 ) );
404 check( !strcmp( buf, "3" ) );
406 tr_snprintf( buf, sizeof( buf ), "%.2f", tr_truncd( nan, 2 ) );
407 check( !strcmp( buf, "nan" ) );
409 return 0;
413 main( void )
415 char *in, *out;
416 int len;
417 int i;
418 int l;
420 /* base64 */
421 out = tr_base64_encode( "YOYO!", -1, &len );
422 check( out );
423 check( !strcmp( out, "WU9ZTyE=\n" ) );
424 check( len == 9 );
425 in = tr_base64_decode( out, -1, &len );
426 check( in );
427 check( !strcmp( in, "YOYO!" ) );
428 check( len == 5 );
429 tr_free( in );
430 tr_free( out );
431 out = tr_base64_encode( NULL, 0, &len );
432 check( out == NULL );
433 check( len == 0 );
435 if( ( i = test_hex( ) ) )
436 return i;
437 if( ( i = test_lowerbound( ) ) )
438 return i;
439 if( ( i = test_strip_positional_args( ) ) )
440 return i;
441 if( ( i = test_strstrip( ) ) )
442 return i;
443 if( ( i = test_buildpath( ) ) )
444 return i;
445 if( ( i = test_utf8( ) ) )
446 return i;
447 if( ( i = test_numbers( ) ) )
448 return i;
449 if( ( i = test_memmem( ) ) )
450 return i;
451 if( ( i = test_array( ) ) )
452 return i;
453 if( ( i = test_url( ) ) )
454 return i;
455 if( ( i = test_truncd( ) ) )
456 return i;
458 /* test that tr_cryptoRandInt() stays in-bounds */
459 for( i = 0; i < 100000; ++i )
461 const int val = tr_cryptoRandInt( 100 );
462 check( val >= 0 );
463 check( val < 100 );
466 /* simple bitfield tests */
467 for( l = 0; l < NUM_LOOPS; ++l )
468 if( ( i = test_bitfields( ) ) )
469 return i;
471 return 0;