static int test_error_propagate (void) { tr_error * err = NULL; tr_error * err2 = NULL; tr_error_set_literal (&err, 1, "oops"); check (err != NULL); check_int_eq (1, err->code); check_streq ("oops", err->message); tr_error_propagate (&err2, &err); check (err2 != NULL); check_int_eq (1, err2->code); check_streq ("oops", err2->message); check (err == NULL); tr_error_propagate_prefixed (&err, &err2, "error: "); check (err != NULL); check_int_eq (1, err->code); check_streq ("error: oops", err->message); check (err2 == NULL); tr_error_propagate (NULL, &err); check (err == NULL); tr_error_free (err2); return 0; }
static int test_static_quarks (void) { int i; for (i=0; i<TR_N_KEYS; i++) { tr_quark q; size_t len; const char * str; str = tr_quark_get_string ((tr_quark)i, &len); check_uint_eq (strlen(str), len); check (tr_quark_lookup (str, len, &q)); check_int_eq (i, (int)q); } for (i=0; i+1<TR_N_KEYS; i++) { size_t len1, len2; const char *str1, *str2; str1 = tr_quark_get_string ((tr_quark)i, &len1); str2 = tr_quark_get_string ((tr_quark)(i+1), &len2); check (strcmp (str1, str2) < 0); } const tr_quark q = tr_quark_new (NULL, TR_BAD_SIZE); check_int_eq (TR_KEY_NONE, (int)q); check_streq ("", tr_quark_get_string (q, NULL)); return 0; }
static int test_error_set (void) { tr_error * err = NULL; tr_error_prefix (&err, "error: "); check (err == NULL); tr_error_set (&err, 1, "error: %s (%d)", "oops", 2); check (err != NULL); check_int_eq (1, err->code); check_streq ("error: oops (2)", err->message); tr_error_clear (&err); check (err == NULL); tr_error_set_literal (&err, 2, "oops"); check (err != NULL); check_int_eq (2, err->code); check_streq ("oops", err->message); tr_error_prefix (&err, "error: "); check (err != NULL); check_int_eq (2, err->code); check_streq ("error: oops", err->message); tr_error_free (err); return 0; }
static int test1 (void) { tr_info inf; tr_ctor * ctor; const char * magnet_link; tr_parse_result parse_result; /* background info @ http://wiki.theory.org/BitTorrent_Magnet-URI_Webseeding */ magnet_link = "magnet:?" "xt=urn:btih:14FFE5DD23188FD5CB53A1D47F1289DB70ABF31E" "&dn=ubuntu+12+04+1+desktop+32+bit" "&tr=http%3A%2F%2Ftracker.publicbt.com%2Fannounce" "&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80" "&ws=http://transmissionbt.com "; ctor = tr_ctorNew (NULL); tr_ctorSetMetainfoFromMagnetLink (ctor, magnet_link); parse_result = tr_torrentParse (ctor, &inf); check_int_eq (inf.fileCount, 0); /* cos it's a magnet link */ check_int_eq (parse_result, TR_PARSE_OK); check_int_eq (inf.trackerCount, 2); check_streq ("http://tracker.publicbt.com/announce", inf.trackers[0].announce); check_streq ("udp://tracker.publicbt.com:80", inf.trackers[1].announce); check_int_eq (inf.webseedCount, 1); check_streq ("http://transmissionbt.com", inf.webseeds[0]); /* cleanup */ tr_metainfoFree (&inf); tr_ctorFree (ctor); return 0; }
static int test_lowerbound (void) { int i; const int A[] = { 1, 2, 3, 3, 3, 5, 8 }; const int expected_pos[] = { 0, 1, 2, 5, 5, 6, 6, 6, 7, 7 }; const bool expected_exact[] = { true, true, true, false, true, false, false, true, false, false }; const int N = sizeof (A) / sizeof (A[0]); for (i=1; i<=10; i++) { bool exact; const int pos = tr_lowerBound (&i, A, N, sizeof (int), compareInts, &exact); #if 0 fprintf (stderr, "searching for %d. ", i); fprintf (stderr, "result: index = %d, ", pos); if (pos != N) fprintf (stderr, "A[%d] == %d\n", pos, A[pos]); else fprintf (stderr, "which is off the end.\n"); #endif check_int_eq (expected_pos[i-1], pos); check_int_eq (expected_exact[i-1], exact); } return 0; }
static int test_static_quarks (void) { int i; for (i=0; i<TR_N_KEYS; i++) { tr_quark q; size_t len; const char * str; str = tr_quark_get_string (i, &len); check_int_eq (strlen(str), len); check (tr_quark_lookup (str, len, &q)); check_int_eq (i, q); } for (i=0; i+1<TR_N_KEYS; i++) { size_t len1, len2; const char *str1, *str2; str1 = tr_quark_get_string (i, &len1); str2 = tr_quark_get_string (i+1, &len2); check (strcmp (str1, str2) < 0); } return 0; }
static int test1 (void) { int i; const char * uri; tr_magnet_info * info; const int dec[] = { 210, 53, 64, 16, 163, 202, 74, 222, 91, 116, 39, 187, 9, 58, 98, 163, 137, 159, 243, 129 }; uri = "magnet:?xt=urn:btih:" "d2354010a3ca4ade5b7427bb093a62a3899ff381" "&dn=Display%20Name" "&tr=http%3A%2F%2Ftracker.openbittorrent.com%2Fannounce" "&tr=http%3A%2F%2Ftracker.opentracker.org%2Fannounce" "&ws=http%3A%2F%2Fserver.webseed.org%2Fpath%2Fto%2Ffile"; info = tr_magnetParse (uri); check (info != NULL); check_int_eq (2, info->trackerCount); check_streq (info->trackers[0], "http://tracker.openbittorrent.com/announce"); check_streq (info->trackers[1], "http://tracker.opentracker.org/announce"); check_int_eq (1, info->webseedCount); check_streq ("http://server.webseed.org/path/to/file", info->webseeds[0]); check_streq ("Display Name", info->displayName); for (i=0; i<20; ++i) check (info->hash[i] == dec[i]); tr_magnetFree (info); info = NULL; /* same thing but in base32 encoding */ uri = "magnet:?xt=urn:btih:" "2I2UAEFDZJFN4W3UE65QSOTCUOEZ744B" "&dn=Display%20Name" "&tr=http%3A%2F%2Ftracker.openbittorrent.com%2Fannounce" "&ws=http%3A%2F%2Fserver.webseed.org%2Fpath%2Fto%2Ffile" "&tr=http%3A%2F%2Ftracker.opentracker.org%2Fannounce"; info = tr_magnetParse (uri); check (info != NULL); check_int_eq (2, info->trackerCount); check_streq ("http://tracker.openbittorrent.com/announce", info->trackers[0]); check_streq ("http://tracker.opentracker.org/announce", info->trackers[1]); check_int_eq (1, info->webseedCount); check_streq ("http://server.webseed.org/path/to/file", info->webseeds[0]); check_streq ("Display Name", info->displayName); for (i=0; i<20; ++i) check (info->hash[i] == dec[i]); tr_magnetFree (info); info = NULL; return 0; }
static int test_elements (void) { const char * in; tr_variant top; const char * str; bool f; double d; int64_t i; int err = 0; tr_quark key; in = "{ \"string\": \"hello world\"," " \"escaped\": \"bell \\b formfeed \\f linefeed \\n carriage return \\r tab \\t\"," " \"int\": 5, " " \"float\": 6.5, " " \"true\": true, " " \"false\": false, " " \"null\": null }"; err = tr_variantFromJson (&top, in, strlen(in)); check_int_eq (0, err); check (tr_variantIsDict (&top)); str = NULL; key = tr_quark_new ("string", 6); check (tr_variantDictFindStr (&top, key, &str, NULL)); check_streq ("hello world", str); check (tr_variantDictFindStr (&top, tr_quark_new("escaped",7), &str, NULL)); check_streq ("bell \b formfeed \f linefeed \n carriage return \r tab \t", str); i = 0; check (tr_variantDictFindInt (&top, tr_quark_new("int",3), &i)); check_int_eq (5, i); d = 0; check (tr_variantDictFindReal (&top, tr_quark_new("float",5), &d)); check_int_eq (65, ((int)(d*10))); f = false; check (tr_variantDictFindBool (&top, tr_quark_new("true",4), &f)); check_int_eq (true, f); check (tr_variantDictFindBool (&top, tr_quark_new("false",5), &f)); check_int_eq (false, f); check (tr_variantDictFindStr (&top, tr_quark_new("null",4), &str, NULL)); check_streq ("", str); if (!err) tr_variantFree (&top); return 0; }
static int testMerge( void ) { tr_benc dest, src; int64_t i; const char * s; /* initial dictionary (default values) */ tr_bencInitDict( &dest, 10 ); tr_bencDictAddInt( &dest, "i1", 1 ); tr_bencDictAddInt( &dest, "i2", 2 ); tr_bencDictAddInt( &dest, "i4", -35 ); /* remains untouched */ tr_bencDictAddStr( &dest, "s5", "abc" ); tr_bencDictAddStr( &dest, "s6", "def" ); tr_bencDictAddStr( &dest, "s7", "127.0.0.1" ); /* remains untouched */ /* new dictionary, will overwrite items in dest */ tr_bencInitDict( &src, 10 ); tr_bencDictAddInt( &src, "i1", 1 ); /* same value */ tr_bencDictAddInt( &src, "i2", 4 ); /* new value */ tr_bencDictAddInt( &src, "i3", 3 ); /* new key:value */ tr_bencDictAddStr( &src, "s5", "abc" ); /* same value */ tr_bencDictAddStr( &src, "s6", "xyz" ); /* new value */ tr_bencDictAddStr( &src, "s8", "ghi" ); /* new key:value */ tr_bencMergeDicts( &dest, /*const*/ &src ); check( tr_bencDictFindInt( &dest, "i1", &i )); check_int_eq (1, i); check( tr_bencDictFindInt( &dest, "i2", &i )); check_int_eq (4, i); check( tr_bencDictFindInt( &dest, "i3", &i )); check_int_eq (3, i); check( tr_bencDictFindInt( &dest, "i4", &i )); check_int_eq (-35, i); check( tr_bencDictFindStr( &dest, "s5", &s )); check_streq ("abc", s); check( tr_bencDictFindStr( &dest, "s6", &s )); check_streq ("xyz", s); check( tr_bencDictFindStr( &dest, "s7", &s )); check_streq ("127.0.0.1", s); check( tr_bencDictFindStr( &dest, "s8", &s )); check_streq ("ghi", s); tr_bencFree( &dest ); tr_bencFree( &src ); return 0; }
static int test_metainfo (void) { size_t i; const struct { int expected_benc_err; int expected_parse_result; const void * benc; } metainfo[] = { { 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt" AFTER_PATH }, /* allow empty components, but not =all= empty components, see bug #5517 */ { 0, TR_PARSE_OK, BEFORE_PATH "0:5:a.txt" AFTER_PATH }, { 0, TR_PARSE_ERR, BEFORE_PATH "0:0:" AFTER_PATH }, /* don't allow path components in a filename */ { 0, TR_PARSE_ERR, BEFORE_PATH "7:a/a.txt" AFTER_PATH }, /* fail on "." components */ { 0, TR_PARSE_ERR, BEFORE_PATH "1:.5:a.txt" AFTER_PATH }, { 0, TR_PARSE_ERR, BEFORE_PATH "5:a.txt1:." AFTER_PATH }, /* fail on ".." components */ { 0, TR_PARSE_ERR, BEFORE_PATH "2:..5:a.txt" AFTER_PATH }, { 0, TR_PARSE_ERR, BEFORE_PATH "5:a.txt2:.." AFTER_PATH }, /* fail on empty string */ { EILSEQ, TR_PARSE_ERR, "" } }; tr_logSetLevel(0); /* yes, we already know these will generate errors, thank you... */ for (i=0; i<(sizeof(metainfo) / sizeof(metainfo[0])); i++) { tr_ctor * ctor = tr_ctorNew (NULL); const int err = tr_ctorSetMetainfo (ctor, metainfo[i].benc, strlen(metainfo[i].benc)); check_int_eq (metainfo[i].expected_benc_err, err); if (!err) { const tr_parse_result parse_result = tr_torrentParse (ctor, NULL); check_int_eq (metainfo[i].expected_parse_result, parse_result); } tr_ctorFree (ctor); } return 0; }
static int testString( const char * str, int isGood ) { tr_benc val; const uint8_t * end = NULL; char * saved; const size_t len = strlen( str ); int savedLen; int err = tr_bencParse( str, str + len, &val, &end ); if( !isGood ) { check( err ); } else { check( !err ); #if 0 fprintf( stderr, "in: [%s]\n", str ); fprintf( stderr, "out:\n%s", tr_bencToStr( &val, TR_FMT_JSON, NULL ) ); #endif check( end == (const uint8_t*)str + len ); saved = tr_bencToStr( &val, TR_FMT_BENC, &savedLen ); check_streq (str, saved); check_int_eq (savedLen, len); tr_free( saved ); tr_bencFree( &val ); } return 0; }
static int test_url (void) { int port; char * scheme; char * host; char * path; char * str; const char * url; url = "http://1"; check (tr_urlParse (url, TR_BAD_SIZE, &scheme, &host, &port, &path)); check_streq ("http", scheme); check_streq ("1", host); check_streq ("/", path); check_int_eq (80, port); tr_free (scheme); tr_free (path); tr_free (host); url = "http://www.some-tracker.org/some/path"; check (tr_urlParse (url, TR_BAD_SIZE, &scheme, &host, &port, &path)); check_streq ("http", scheme); check_streq ("www.some-tracker.org", host); check_streq ("/some/path", path); check_int_eq (80, port); tr_free (scheme); tr_free (path); tr_free (host); url = "http://www.some-tracker.org:80/some/path"; check (tr_urlParse (url, TR_BAD_SIZE, &scheme, &host, &port, &path)); check_streq ("http", scheme); check_streq ("www.some-tracker.org", host); check_streq ("/some/path", path); check_int_eq (80, port); tr_free (scheme); tr_free (path); tr_free (host); url = "http%3A%2F%2Fwww.example.com%2F~user%2F%3Ftest%3D1%26test1%3D2"; str = tr_http_unescape (url, strlen (url)); check_streq ("http://www.example.com/~user/?test=1&test1=2", str); tr_free (str); return 0; }
static int test_list (void) { size_t len; int64_t i; const char * str; tr_variant top; tr_rpc_parse_list_str (&top, "12", -1); check (tr_variantIsInt (&top)); check (tr_variantGetInt (&top, &i)); check_int_eq (12, i); tr_variantFree (&top); tr_rpc_parse_list_str (&top, "12", 1); check (tr_variantIsInt (&top)); check (tr_variantGetInt (&top, &i)); check_int_eq (1, i); tr_variantFree (&top); tr_rpc_parse_list_str (&top, "6,7", -1); check (tr_variantIsList (&top)); check (tr_variantListSize (&top) == 2); check (tr_variantGetInt (tr_variantListChild (&top, 0), &i)); check_int_eq (6, i); check (tr_variantGetInt (tr_variantListChild (&top, 1), &i)); check_int_eq (7, i); tr_variantFree (&top); tr_rpc_parse_list_str (&top, "asdf", -1); check (tr_variantIsString (&top)); check (tr_variantGetStr (&top, &str, &len)); check_int_eq (4, len); check_streq ("asdf", str); tr_variantFree (&top); tr_rpc_parse_list_str (&top, "1,3-5", -1); check (tr_variantIsList (&top)); check (tr_variantListSize (&top) == 4); check (tr_variantGetInt (tr_variantListChild (&top, 0), &i)); check_int_eq (1, i); check (tr_variantGetInt (tr_variantListChild (&top, 1), &i)); check_int_eq (3, i); check (tr_variantGetInt (tr_variantListChild (&top, 2), &i)); check_int_eq (4, i); check (tr_variantGetInt (tr_variantListChild (&top, 3), &i)); check_int_eq (5, i); tr_variantFree (&top); return 0; }
static int test1 (void) { const char * in = "{\n" " \"headers\": {\n" " \"type\": \"request\",\n" " \"tag\": 666\n" " },\n" " \"body\": {\n" " \"name\": \"torrent-info\",\n" " \"arguments\": {\n" " \"ids\": [ 7, 10 ]\n" " }\n" " }\n" "}\n"; tr_variant top, *headers, *body, *args, *ids; const char * str; int64_t i; const int err = tr_variantFromJson (&top, in, strlen(in)); check (!err); check (tr_variantIsDict (&top)); check ((headers = tr_variantDictFind (&top, tr_quark_new("headers",7)))); check (tr_variantIsDict (headers)); check (tr_variantDictFindStr (headers, tr_quark_new("type",4), &str, NULL)); check_streq ("request", str); check (tr_variantDictFindInt (headers, TR_KEY_tag, &i)); check_int_eq (666, i); check ((body = tr_variantDictFind (&top, tr_quark_new("body",4)))); check (tr_variantDictFindStr (body, TR_KEY_name, &str, NULL)); check_streq ("torrent-info", str); check ((args = tr_variantDictFind (body, tr_quark_new("arguments",9)))); check (tr_variantIsDict (args)); check ((ids = tr_variantDictFind (args, TR_KEY_ids))); check (tr_variantIsList (ids)); check_int_eq (2, tr_variantListSize (ids)); check (tr_variantGetInt (tr_variantListChild (ids, 0), &i)); check_int_eq (7, i); check (tr_variantGetInt (tr_variantListChild (ids, 1), &i)); check_int_eq (10, i); tr_variantFree (&top); return 0; }
static int test_env (void) { const char * test_key = "TR_TEST_ENV"; int x; char * s; unsetenv (test_key); check (!tr_env_key_exists (test_key)); x = tr_env_get_int (test_key, 123); check_int_eq (123, x); s = tr_env_get_string (test_key, NULL); check (s == NULL); s = tr_env_get_string (test_key, "a"); check_streq ("a", s); tr_free (s); setenv (test_key, "", 1); check (tr_env_key_exists (test_key)); x = tr_env_get_int (test_key, 456); check_int_eq (456, x); s = tr_env_get_string (test_key, NULL); check_streq ("", s); tr_free (s); s = tr_env_get_string (test_key, "b"); check_streq ("", s); tr_free (s); setenv (test_key, "135", 1); check (tr_env_key_exists (test_key)); x = tr_env_get_int (test_key, 789); check_int_eq (135, x); s = tr_env_get_string (test_key, NULL); check_streq ("135", s); tr_free (s); s = tr_env_get_string (test_key, "c"); check_streq ("135", s); tr_free (s); return 0; }
static int test_parsing (void) { char * path; tr_session * session; /* init the session */ session = libttest_session_init (NULL); check (!tr_blocklistExists (session)); check_int_eq (0, tr_blocklistGetRuleCount (session)); /* init the blocklist */ path = tr_buildPath (tr_sessionGetConfigDir(session), "blocklists", "level1", NULL); create_text_file (path, contents1); tr_free (path); tr_sessionReloadBlocklists (session); check (tr_blocklistExists (session)); check_int_eq (4, tr_blocklistGetRuleCount (session)); /* enable the blocklist */ check (!tr_blocklistIsEnabled (session)); tr_blocklistSetEnabled (session, true); check (tr_blocklistIsEnabled (session)); /* test blocked addresses */ check (!address_is_blocked (session, "216.16.1.143")); check ( address_is_blocked (session, "216.16.1.144")); check ( address_is_blocked (session, "216.16.1.145")); check ( address_is_blocked (session, "216.16.1.146")); check ( address_is_blocked (session, "216.16.1.147")); check ( address_is_blocked (session, "216.16.1.148")); check ( address_is_blocked (session, "216.16.1.149")); check ( address_is_blocked (session, "216.16.1.150")); check ( address_is_blocked (session, "216.16.1.151")); check (!address_is_blocked (session, "216.16.1.152")); check (!address_is_blocked (session, "216.16.1.153")); check (!address_is_blocked (session, "217.0.0.1")); check (!address_is_blocked (session, "255.0.0.1")); /* cleanup */ libttest_session_close (session); return 0; }
static int testStr( void ) { uint8_t buf[128]; int err; const uint8_t * end; const uint8_t * str; size_t len; /* good string */ tr_snprintf( (char*)buf, sizeof( buf ), "4:boat" ); err = tr_bencParseStr( buf, buf + 6, &end, &str, &len ); check_int_eq (0, err); check_int_eq (4, len); check( !strncmp( (char*)str, "boat", len ) ); check( end == buf + 6 ); str = NULL; end = NULL; len = 0; /* string goes past end of buffer */ err = tr_bencParseStr( buf, buf + 5, &end, &str, &len ); check_int_eq (EILSEQ, err); check_int_eq (0, len); check( str == NULL ); check( end == NULL ); check( !len ); /* empty string */ tr_snprintf( (char*)buf, sizeof( buf ), "0:" ); err = tr_bencParseStr( buf, buf + 2, &end, &str, &len ); check_int_eq (0, err); check_int_eq (0, len); check( !*str ); check( end == buf + 2 ); str = NULL; end = NULL; len = 0; /* short string */ tr_snprintf( (char*)buf, sizeof( buf ), "3:boat" ); err = tr_bencParseStr( buf, buf + 6, &end, &str, &len ); check_int_eq (0, err); check_int_eq (3, len); check( !strncmp( (char*)str, "boa", len ) ); check( end == buf + 5 ); str = NULL; end = NULL; len = 0; return 0; }
static int test_array (void) { size_t i; size_t array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; size_t n = sizeof (array) / sizeof (array[0]); tr_removeElementFromArray (array, 5u, sizeof (size_t), n--); for (i=0; i<n; ++i) check_int_eq ((i<5 ? i : i+1), array[i]); tr_removeElementFromArray (array, 0u, sizeof (size_t), n--); for (i=0; i<n; ++i) check_int_eq ((i<4 ? i+1 : i+2), array[i]); tr_removeElementFromArray (array, n-1, sizeof (size_t), n); n--; for (i=0; i<n; ++i) check_int_eq ((i<4 ? i+1 : i+2), array[i]); return 0; }
static int test_base64( void ) { char *in, *out; int len; /* base64 */ out = tr_base64_encode( "YOYO!", -1, &len ); check_streq ("WU9ZTyE=", out); check_int_eq (8, len); in = tr_base64_decode( out, -1, &len ); check_streq ("YOYO!", in); check_int_eq (5, len); tr_free( in ); tr_free( out ); out = tr_base64_encode( NULL, 0, &len ); check( out == NULL ); check_int_eq (0, len); return 0; }
static int testParse2( void ) { tr_benc top; tr_benc top2; int64_t intVal; const char * strVal; double realVal; bool boolVal; int len; char * benc; const uint8_t * end; tr_bencInitDict( &top, 0 ); tr_bencDictAddBool( &top, "this-is-a-bool", true ); tr_bencDictAddInt( &top, "this-is-an-int", 1234 ); tr_bencDictAddReal( &top, "this-is-a-real", 0.5 ); tr_bencDictAddStr( &top, "this-is-a-string", "this-is-a-string" ); benc = tr_bencToStr( &top, TR_FMT_BENC, &len ); check_streq( "d14:this-is-a-booli1e14:this-is-a-real8:0.50000016:this-is-a-string16:this-is-a-string14:this-is-an-inti1234ee", benc ); check( !tr_bencParse( benc, benc+len, &top2, &end ) ); check( (char*)end == benc + len ); check( tr_bencIsDict( &top2 ) ); check( tr_bencDictFindInt( &top, "this-is-an-int", &intVal ) ); check_int_eq (1234, intVal); check( tr_bencDictFindBool( &top, "this-is-a-bool", &boolVal ) ); check( boolVal == true ); check( tr_bencDictFindStr( &top, "this-is-a-string", &strVal ) ); check_streq ("this-is-a-string", strVal); check( tr_bencDictFindReal( &top, "this-is-a-real", &realVal ) ); check_int_eq (50, (int)(realVal*100)); tr_bencFree( &top2 ); tr_free( benc ); tr_bencFree( &top ); return 0; }
static int test_updating (void) { char * path; tr_session * session; /* init the session */ session = libttest_session_init (NULL); path = tr_buildPath (tr_sessionGetConfigDir(session), "blocklists", "level1", NULL); /* no blocklist to start with... */ check_int_eq (0, tr_blocklistGetRuleCount (session)); /* test that updated source files will get loaded */ create_text_file (path, contents1); tr_sessionReloadBlocklists (session); check_int_eq (4, tr_blocklistGetRuleCount (session)); /* test that updated source files will get loaded */ create_text_file (path, contents2); tr_sessionReloadBlocklists (session); check_int_eq (5, tr_blocklistGetRuleCount (session)); /* test that updated source files will get loaded */ create_text_file (path, contents1); tr_sessionReloadBlocklists (session); check_int_eq (4, tr_blocklistGetRuleCount (session)); /* ensure that new files, if bad, get skipped */ create_text_file (path, "# nothing useful\n"); tr_sessionReloadBlocklists (session); check_int_eq (4, tr_blocklistGetRuleCount (session)); /* cleanup */ libttest_session_close (session); tr_free (path); return 0; }
static int test_unescape (void) { const char * in = "{ \"string-1\": \"\\/usr\\/lib\" }"; tr_variant top; const char * str; const int err = tr_variantFromJson (&top, in, strlen(in)); check_int_eq (0, err); check (tr_variantDictFindStr (&top, tr_quark_new("string-1",8), &str, NULL)); check_streq ("/usr/lib", str); tr_variantFree (&top); return 0; }
static int run_test (int argc, const char ** argv, int expected_n, int * expected_c, const char ** expected_optarg) { int c; int n; const char * optarg; n = 0; tr_optind = 1; while ((c = tr_getopt ("summary", argc, argv, options, &optarg))) { check (n < expected_n); check_int_eq (expected_c[n], c); check_streq (optarg, expected_optarg[n]); ++n; } check_int_eq (expected_n, n); return 0; }
static int test_quickfindFirst (void) { size_t i; const size_t k = 10; const size_t n = 100; const size_t n_trials = 1000; int * buf = tr_new (int, n); for (i=0; i<n_trials; ++i) check_int_eq (0, test_quickFindFirst_Iteration (k, n, buf, 100)); tr_free (buf); return 0; }
static int test_single_file_impl (const tr_tracker_info * trackers, const size_t trackerCount, const void * payload, const size_t payloadSize, const char * comment, bool isPrivate) { char* sandbox; char* input_file; char* torrent_file; tr_metainfo_builder* builder; tr_ctor * ctor; tr_parse_result parse_result; tr_info inf; char * tmpstr; /* set up our local test sandbox */ sandbox = libtest_sandbox_create(); /* create a single input file */ input_file = tr_buildPath (sandbox, "test.XXXXXX", NULL); libtest_create_tmpfile_with_contents (input_file, payload, payloadSize); builder = tr_metaInfoBuilderCreate (input_file); check_streq (input_file, builder->top); check_int_eq (1, builder->fileCount); check_streq (input_file, builder->files[0].filename); check_int_eq (payloadSize, builder->files[0].size); check_int_eq (payloadSize, builder->totalSize); check (!builder->isFolder); check (!builder->abortFlag); /* have tr_makeMetaInfo() build the .torrent file */ torrent_file = tr_strdup_printf ("%s.torrent", input_file); tr_makeMetaInfo (builder, torrent_file, trackers, trackerCount, comment, isPrivate); check (isPrivate == builder->isPrivate); check_streq (torrent_file, builder->outputFile); check_streq (comment, builder->comment); check_int_eq (trackerCount, builder->trackerCount); while (!builder->isDone) tr_wait_msec (100); /* now let's check our work: parse the .torrent file */ ctor = tr_ctorNew (NULL); libttest_sync (); tr_ctorSetMetainfoFromFile (ctor, torrent_file); parse_result = tr_torrentParse (ctor, &inf); check_int_eq (TR_PARSE_OK, parse_result); /* quick check of some of the parsed metainfo */ check_int_eq (payloadSize, inf.totalSize); tmpstr = tr_sys_path_basename (input_file, NULL); check_streq (tmpstr, inf.name); tr_free (tmpstr); check_streq (comment, inf.comment); check_int_eq (1, inf.fileCount); check_int_eq (isPrivate, inf.isPrivate); check (!inf.isFolder); check_int_eq (trackerCount, inf.trackerCount); /* cleanup */ tr_free (torrent_file); tr_free (input_file); tr_ctorFree (ctor); tr_metainfoFree (&inf); tr_metaInfoBuilderFree (builder); libtest_sandbox_destroy (sandbox); tr_free (sandbox); return 0; }
static int test_single_directory_impl (const tr_tracker_info * trackers, const size_t trackerCount, const void ** payloads, const size_t * payloadSizes, const size_t payloadCount, const char * comment, const bool isPrivate) { char* sandbox; char* torrent_file; tr_metainfo_builder* builder; tr_ctor * ctor; tr_parse_result parse_result; tr_info inf; char * top; char ** files; size_t totalSize; size_t i; char* tmpstr; /* set up our local test sandbox */ sandbox = libtest_sandbox_create(); /* create the top temp directory */ top = tr_buildPath (sandbox, "folder.XXXXXX", NULL); tr_sys_dir_create_temp (top, NULL); /* build the payload files that go into the top temp directory */ files = tr_new (char*, payloadCount); totalSize = 0; for (i=0; i<payloadCount; i++) { char tmpl[16]; tr_snprintf (tmpl, sizeof(tmpl), "file.%04zu%s", i, "XXXXXX"); files[i] = tr_buildPath (top, tmpl, NULL); libtest_create_tmpfile_with_contents (files[i], payloads[i], payloadSizes[i]); totalSize += payloadSizes[i]; } libttest_sync (); /* init the builder */ builder = tr_metaInfoBuilderCreate (top); check (!builder->abortFlag); check_streq (top, builder->top); check_int_eq (payloadCount, builder->fileCount); check_int_eq (totalSize, builder->totalSize); check (builder->isFolder); for (i=0; i<builder->fileCount; i++) { check_streq (files[i], builder->files[i].filename); check_int_eq (payloadSizes[i], builder->files[i].size); } /* call tr_makeMetaInfo() to build the .torrent file */ torrent_file = tr_strdup_printf ("%s.torrent", top); tr_makeMetaInfo (builder, torrent_file, trackers, trackerCount, comment, isPrivate); check (isPrivate == builder->isPrivate); check_streq (torrent_file, builder->outputFile); check_streq (comment, builder->comment); check_int_eq (trackerCount, builder->trackerCount); while (!builder->isDone) tr_wait_msec (100); /* now let's check our work: parse the .torrent file */ ctor = tr_ctorNew (NULL); libttest_sync (); tr_ctorSetMetainfoFromFile (ctor, torrent_file); parse_result = tr_torrentParse (ctor, &inf); check_int_eq (TR_PARSE_OK, parse_result); /* quick check of some of the parsed metainfo */ check_int_eq (totalSize, inf.totalSize); tmpstr = tr_sys_path_basename (top, NULL); check_streq (tmpstr, inf.name); tr_free (tmpstr); check_streq (comment, inf.comment); check_int_eq (payloadCount, inf.fileCount); check_int_eq (isPrivate, inf.isPrivate); check_int_eq (builder->isFolder, inf.isFolder); check_int_eq (trackerCount, inf.trackerCount); /* cleanup */ tr_free (torrent_file); tr_ctorFree (ctor); tr_metainfoFree (&inf); tr_metaInfoBuilderFree (builder); for (i=0; i<payloadCount; i++) tr_free (files[i]); tr_free (files); libtest_sandbox_destroy (sandbox); tr_free (sandbox); tr_free (top); return 0; }
static int testParse( void ) { tr_benc val; tr_benc * child; tr_benc * child2; uint8_t buf[512]; const uint8_t * end; int err; int len; int64_t i; char * saved; tr_snprintf( (char*)buf, sizeof( buf ), "i64e" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( tr_bencGetInt( &val, &i ) ); check_int_eq (64, i); check( end == buf + 4 ); tr_bencFree( &val ); tr_snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + strlen( (char*)buf ) ); check( val.val.l.count == 3 ); check( tr_bencGetInt( &val.val.l.vals[0], &i ) ); check_int_eq (64, i); check( tr_bencGetInt( &val.val.l.vals[1], &i ) ); check_int_eq (32, i); check( tr_bencGetInt( &val.val.l.vals[2], &i ) ); check_int_eq (16, i); saved = tr_bencToStr( &val, TR_FMT_BENC, &len ); check_streq ((char*)buf, saved); tr_free( saved ); tr_bencFree( &val ); end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "lllee" ); err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end ); check( err ); check( end == NULL ); end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "le" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + 2 ); saved = tr_bencToStr( &val, TR_FMT_BENC, &len ); check_streq( "le", saved ); tr_free( saved ); tr_bencFree( &val ); if( ( err = testString( "llleee", true ) ) ) return err; if( ( err = testString( "d3:cow3:moo4:spam4:eggse", true ) ) ) return err; if( ( err = testString( "d4:spaml1:a1:bee", true ) ) ) return err; if( ( err = testString( "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee", true ) ) ) return err; if( ( err = testString( "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", true ) ) ) return err; if( ( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", true ) ) ) return err; if( ( err = testString( "d1:ai0e1:be", false ) ) ) /* odd number of children */ return err; if( ( err = testString( "", false ) ) ) return err; if( ( err = testString( " ", false ) ) ) return err; /* nested containers * parse an unsorted dict * save as a sorted dict */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + strlen( (const char*)buf ) ); check( ( child = tr_bencListChild( &val, 0 ) ) ); check( ( child2 = tr_bencListChild( child, 0 ) ) ); saved = tr_bencToStr( &val, TR_FMT_BENC, &len ); check_streq( "lld1:ai64e1:bi32eeee", saved ); tr_free( saved ); tr_bencFree( &val ); /* too many endings */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "leee" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + 2 ); saved = tr_bencToStr( &val, TR_FMT_BENC, &len ); check_streq( "le", saved ); tr_free( saved ); tr_bencFree( &val ); /* no ending */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "l1:a1:b1:c" ); err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end ); check( err ); /* incomplete string */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "1:" ); err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end ); check( err ); return 0; }
static int testInt( void ) { uint8_t buf[128]; int64_t val; int err; const uint8_t * end; /* good int string */ tr_snprintf( (char*)buf, sizeof( buf ), "i64e" ); err = tr_bencParseInt( buf, buf + 4, &end, &val ); check_int_eq( 0, err ); check_int_eq( 64, val ); check( (buf + 4) == end ); /* missing 'e' */ end = NULL; val = 888; err = tr_bencParseInt( buf, buf + 3, &end, &val ); check_int_eq( EILSEQ, err ); check_int_eq( 888, val ); check( end == NULL ); /* empty buffer */ err = tr_bencParseInt( buf, buf + 0, &end, &val ); check_int_eq( EILSEQ, err ); check_int_eq( 888, val ); check( end == NULL ); /* bad number */ tr_snprintf( (char*)buf, sizeof( buf ), "i6z4e" ); err = tr_bencParseInt( buf, buf + 5, &end, &val ); check_int_eq( EILSEQ, err ); check_int_eq( 888, val ); check( end == NULL ); /* negative number */ tr_snprintf( (char*)buf, sizeof( buf ), "i-3e" ); err = tr_bencParseInt( buf, buf + 4, &end, &val ); check_int_eq( 0, err ); check_int_eq( -3, val ); check( (buf + 4) == end ); /* zero */ tr_snprintf( (char*)buf, sizeof( buf ), "i0e" ); err = tr_bencParseInt( buf, buf + 4, &end, &val ); check_int_eq( 0, err ); check_int_eq( 0, val ); check( (buf + 3) == end ); /* no leading zeroes allowed */ val = 0; end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "i04e" ); err = tr_bencParseInt( buf, buf + 4, &end, &val ); check_int_eq( EILSEQ, err ); check_int_eq( 0, val ); check( NULL == end ); return 0; }
static int test_numbers (void) { int i; int count; int * numbers; numbers = tr_parseNumberRange ("1-10,13,16-19", TR_BAD_SIZE, &count); check_int_eq (15, count); check_int_eq (1, numbers[0]); check_int_eq (6, numbers[5]); check_int_eq (10, numbers[9]); check_int_eq (13, numbers[10]); check_int_eq (16, numbers[11]); check_int_eq (19, numbers[14]); tr_free (numbers); numbers = tr_parseNumberRange ("1-5,3-7,2-6", TR_BAD_SIZE, &count); check (count == 7); check (numbers != NULL); for (i=0; i<count; ++i) check_int_eq (i+1, numbers[i]); tr_free (numbers); numbers = tr_parseNumberRange ("1-Hello", TR_BAD_SIZE, &count); check_int_eq (0, count); check (numbers == NULL); numbers = tr_parseNumberRange ("1-", TR_BAD_SIZE, &count); check_int_eq (0, count); check (numbers == NULL); numbers = tr_parseNumberRange ("Hello", TR_BAD_SIZE, &count); check_int_eq (0, count); check (numbers == NULL); return 0; }
static int test_get_info (void) { char * const test_dir = create_test_dir (__FUNCTION__); tr_sys_path_info info; tr_sys_file_t fd; tr_error * err = NULL; char * path1, * path2; time_t t; path1 = tr_buildPath (test_dir, "a", NULL); path2 = tr_buildPath (test_dir, "b", NULL); /* Can't get info of non-existent file/directory */ check (!tr_sys_path_get_info (path1, 0, &info, &err)); check (err != NULL); tr_error_clear (&err); t = time (NULL); libtest_create_file_with_string_contents (path1, "test"); /* Good file info */ clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); /* Good file info (by handle) */ fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL); clear_path_info (&info); check (tr_sys_file_get_info (fd, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_file_close (fd, NULL); tr_sys_path_remove (path1, NULL); /* Good directory info */ t = time (NULL); tr_sys_dir_create (path1, 0, 0777, NULL); clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type); check (info.size != (uint64_t) -1); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_path_remove (path1, NULL); if (create_symlink (path1, path2, false)) { /* Can't get info of non-existent file/directory */ check (!tr_sys_path_get_info (path1, 0, &info, &err)); check (err != NULL); tr_error_clear (&err); t = time (NULL); libtest_create_file_with_string_contents (path2, "test"); /* Good file info */ clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); /* Good file info (by handle) */ fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL); clear_path_info (&info); check (tr_sys_file_get_info (fd, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_file_close (fd, NULL); tr_sys_path_remove (path2, NULL); /* Good directory info */ t = time (NULL); tr_sys_dir_create (path2, 0, 0777, NULL); clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type); check (info.size != (uint64_t) -1); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_path_remove (path2, NULL); tr_sys_path_remove (path1, NULL); } else { fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } tr_free (path2); tr_free (path1); tr_free (test_dir); return 0; }