2014-01-19 01:09:44 +00:00
|
|
|
/*
|
|
|
|
* This file Copyright (C) 2013-2014 Mnemosyne LLC
|
|
|
|
*
|
2014-01-21 03:10:30 +00:00
|
|
|
* It may be used under the GNU GPL versions 2 or 3
|
2014-01-19 01:09:44 +00:00
|
|
|
* or any future license endorsed by Mnemosyne LLC.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-04-21 07:40:57 +00:00
|
|
|
#include <string.h> /* strlen() */
|
2012-12-22 20:35:19 +00:00
|
|
|
|
2013-01-24 16:04:09 +00:00
|
|
|
#include <locale.h> /* setlocale() */
|
|
|
|
|
2015-05-04 20:06:05 +00:00
|
|
|
#define __LIBTRANSMISSION_VARIANT_MODULE__
|
2008-05-11 22:42:53 +00:00
|
|
|
#include "transmission.h"
|
|
|
|
#include "utils.h" /* tr_free */
|
2012-12-14 04:34:42 +00:00
|
|
|
#include "variant.h"
|
2012-12-22 20:35:19 +00:00
|
|
|
#include "variant-common.h"
|
2012-08-18 16:07:05 +00:00
|
|
|
#include "libtransmission-test.h"
|
2008-05-11 22:42:53 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static int test_elements(void)
|
2012-11-11 04:20:15 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* in;
|
2012-12-14 04:34:42 +00:00
|
|
|
tr_variant top;
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* str;
|
2012-11-11 04:20:15 +00:00
|
|
|
bool f;
|
|
|
|
double d;
|
|
|
|
int64_t i;
|
|
|
|
int err = 0;
|
2012-12-22 20:35:19 +00:00
|
|
|
tr_quark key;
|
2012-11-11 04:20:15 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
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));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(err, ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(&top));
|
2012-11-11 04:20:15 +00:00
|
|
|
str = NULL;
|
2017-04-19 12:04:45 +00:00
|
|
|
key = tr_quark_new("string", 6);
|
|
|
|
check(tr_variantDictFindStr(&top, key, &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "hello world");
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindStr(&top, tr_quark_new("escaped", 7), &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "bell \b formfeed \f linefeed \n carriage return \r tab \t");
|
2012-11-11 04:20:15 +00:00
|
|
|
i = 0;
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindInt(&top, tr_quark_new("int", 3), &i));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(i, ==, 5);
|
2012-11-11 04:20:15 +00:00
|
|
|
d = 0;
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindReal(&top, tr_quark_new("float", 5), &d));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(((int)(d * 10)), ==, 65);
|
2012-11-11 04:20:15 +00:00
|
|
|
f = false;
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindBool(&top, tr_quark_new("true", 4), &f));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(f, ==, true);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindBool(&top, tr_quark_new("false", 5), &f));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(f, ==, false);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindStr(&top, tr_quark_new("null", 4), &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "");
|
2012-11-11 04:20:15 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (err == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
tr_variantFree(&top);
|
|
|
|
}
|
2008-08-19 23:11:35 +00:00
|
|
|
|
2012-11-11 04:20:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
static int test_utf8(void)
|
2008-08-18 03:10:59 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* in = "{ \"key\": \"Letöltések\" }";
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_variant top;
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* str;
|
2017-04-19 12:04:45 +00:00
|
|
|
char* json;
|
|
|
|
int err;
|
2017-04-20 16:02:19 +00:00
|
|
|
tr_quark const key = tr_quark_new("key", 3);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
err = tr_variantFromJson(&top, in, strlen(in));
|
2017-04-30 16:25:26 +00:00
|
|
|
check(err == 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(&top));
|
|
|
|
check(tr_variantDictFindStr(&top, key, &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "Letöltések");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (err == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
tr_variantFree(&top);
|
|
|
|
}
|
2008-08-18 03:10:59 +00:00
|
|
|
|
2008-08-19 23:11:35 +00:00
|
|
|
in = "{ \"key\": \"\\u005C\" }";
|
2017-04-19 12:04:45 +00:00
|
|
|
err = tr_variantFromJson(&top, in, strlen(in));
|
2017-04-30 16:25:26 +00:00
|
|
|
check(err == 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(&top));
|
|
|
|
check(tr_variantDictFindStr(&top, key, &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "\\");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (err == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
tr_variantFree(&top);
|
|
|
|
}
|
2008-08-18 03:10:59 +00:00
|
|
|
|
2008-08-19 23:11:35 +00:00
|
|
|
/**
|
|
|
|
* 1. Feed it JSON-escaped nonascii to the JSON decoder.
|
|
|
|
* 2. Confirm that the result is UTF-8.
|
|
|
|
* 3. Feed the same UTF-8 back into the JSON encoder.
|
|
|
|
* 4. Confirm that the result is JSON-escaped.
|
|
|
|
* 5. Dogfood that result back into the parser.
|
|
|
|
* 6. Confirm that the result is UTF-8.
|
2008-09-23 19:11:04 +00:00
|
|
|
*/
|
2008-08-19 23:11:35 +00:00
|
|
|
in = "{ \"key\": \"Let\\u00f6lt\\u00e9sek\" }";
|
2017-04-19 12:04:45 +00:00
|
|
|
err = tr_variantFromJson(&top, in, strlen(in));
|
2017-04-30 16:25:26 +00:00
|
|
|
check(err == 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(&top));
|
|
|
|
check(tr_variantDictFindStr(&top, key, &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "Letöltések");
|
2017-04-19 12:04:45 +00:00
|
|
|
json = tr_variantToStr(&top, TR_VARIANT_FMT_JSON, NULL);
|
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (err == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
tr_variantFree(&top);
|
|
|
|
}
|
|
|
|
|
2017-05-23 19:17:17 +00:00
|
|
|
check(json != NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(strstr(json, "\\u00f6") != NULL);
|
|
|
|
check(strstr(json, "\\u00e9") != NULL);
|
|
|
|
err = tr_variantFromJson(&top, json, strlen(json));
|
2017-04-30 16:25:26 +00:00
|
|
|
check(err == 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(&top));
|
|
|
|
check(tr_variantDictFindStr(&top, key, &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "Letöltések");
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (err == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
tr_variantFree(&top);
|
|
|
|
}
|
|
|
|
|
|
|
|
tr_free(json);
|
2008-08-19 23:11:35 +00:00
|
|
|
|
2008-08-18 03:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static int test1(void)
|
2008-05-11 22:42:53 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* in =
|
2008-05-11 22:42:53 +00:00
|
|
|
"{\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";
|
2017-05-01 15:46:41 +00:00
|
|
|
tr_variant top;
|
|
|
|
tr_variant* headers;
|
|
|
|
tr_variant* body;
|
|
|
|
tr_variant* args;
|
|
|
|
tr_variant* ids;
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* str;
|
2017-04-19 12:04:45 +00:00
|
|
|
int64_t i;
|
2017-04-20 16:02:19 +00:00
|
|
|
int const err = tr_variantFromJson(&top, in, strlen(in));
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
check(err == 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(&top));
|
2017-04-30 16:25:26 +00:00
|
|
|
check((headers = tr_variantDictFind(&top, tr_quark_new("headers", 7))) != NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(headers));
|
|
|
|
check(tr_variantDictFindStr(headers, tr_quark_new("type", 4), &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "request");
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindInt(headers, TR_KEY_tag, &i));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(i, ==, 666);
|
2017-04-30 16:25:26 +00:00
|
|
|
check((body = tr_variantDictFind(&top, tr_quark_new("body", 4))) != NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindStr(body, TR_KEY_name, &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "torrent-info");
|
2017-04-30 16:25:26 +00:00
|
|
|
check((args = tr_variantDictFind(body, tr_quark_new("arguments", 9))) != NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsDict(args));
|
2017-04-30 16:25:26 +00:00
|
|
|
check((ids = tr_variantDictFind(args, TR_KEY_ids)) != NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantIsList(ids));
|
2017-05-29 20:39:51 +00:00
|
|
|
check_uint(tr_variantListSize(ids), ==, 2);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantGetInt(tr_variantListChild(ids, 0), &i));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(i, ==, 7);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantGetInt(tr_variantListChild(ids, 1), &i));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(i, ==, 10);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
tr_variantFree(&top);
|
2008-05-11 22:42:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static int test2(void)
|
2009-02-18 16:47:27 +00:00
|
|
|
{
|
2012-12-14 04:34:42 +00:00
|
|
|
tr_variant top;
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* in = " ";
|
2009-04-05 23:16:45 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
top.type = 0;
|
2017-04-19 12:04:45 +00:00
|
|
|
err = tr_variantFromJson(&top, in, strlen(in));
|
2009-02-18 16:47:27 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
check(err != 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(!tr_variantIsDict(&top));
|
2009-02-18 16:47:27 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static int test3(void)
|
2010-04-15 19:27:47 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* in =
|
2017-04-19 12:04:45 +00:00
|
|
|
"{ \"error\": 2,"
|
|
|
|
" \"errorString\": \"torrent not registered with this tracker 6UHsVW'*C\","
|
|
|
|
" \"eta\": 262792,"
|
|
|
|
" \"id\": 25,"
|
|
|
|
" \"leftUntilDone\": 2275655680 }";
|
2012-12-14 04:34:42 +00:00
|
|
|
tr_variant top;
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* str;
|
2010-04-15 19:27:47 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
int const err = tr_variantFromJson(&top, in, strlen(in));
|
2017-04-30 16:25:26 +00:00
|
|
|
check(err == 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindStr(&top, TR_KEY_errorString, &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "torrent not registered with this tracker 6UHsVW'*C");
|
2010-04-15 19:27:47 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_variantFree(&top);
|
2010-04-15 19:27:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static int test_unescape(void)
|
2012-11-27 23:21:13 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* in = "{ \"string-1\": \"\\/usr\\/lib\" }";
|
2012-12-14 04:34:42 +00:00
|
|
|
tr_variant top;
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* str;
|
2012-11-27 23:21:13 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
int const err = tr_variantFromJson(&top, in, strlen(in));
|
2017-05-29 20:22:36 +00:00
|
|
|
check_int(err, ==, 0);
|
2017-04-19 12:04:45 +00:00
|
|
|
check(tr_variantDictFindStr(&top, tr_quark_new("string-1", 8), &str, NULL));
|
2017-05-29 19:48:02 +00:00
|
|
|
check_str(str, ==, "/usr/lib");
|
2012-11-27 23:21:13 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_variantFree(&top);
|
2012-11-27 23:21:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
int main(void)
|
2008-05-11 22:42:53 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* comma_locales[] =
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
"da_DK.UTF-8",
|
|
|
|
"fr_FR.UTF-8",
|
|
|
|
"ru_RU.UTF-8"
|
|
|
|
};
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
testFunc const tests[] =
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
test_elements,
|
|
|
|
test_utf8,
|
|
|
|
test1,
|
|
|
|
test2,
|
|
|
|
test3,
|
|
|
|
test_unescape
|
|
|
|
};
|
|
|
|
|
|
|
|
/* run the tests in a locale with a decimal point of '.' */
|
|
|
|
setlocale(LC_NUMERIC, "C");
|
|
|
|
|
2017-05-29 17:05:24 +00:00
|
|
|
int ret = runTests(tests, NUM_TESTS(tests));
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
/* run the tests in a locale with a decimal point of ',' */
|
2017-05-13 22:38:31 +00:00
|
|
|
bool is_locale_set = false;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
for (size_t i = 0; !is_locale_set && i < TR_N_ELEMENTS(comma_locales); ++i)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2017-05-13 22:38:31 +00:00
|
|
|
is_locale_set = setlocale(LC_NUMERIC, comma_locales[i]) != NULL;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
if (!is_locale_set)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "WARNING: unable to run locale-specific json tests. add a locale like %s or %s\n", comma_locales[0],
|
|
|
|
comma_locales[1]);
|
|
|
|
}
|
2017-05-29 17:05:24 +00:00
|
|
|
else
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2017-05-29 17:05:24 +00:00
|
|
|
ret += runTests(tests, NUM_TESTS(tests));
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2017-05-29 17:05:24 +00:00
|
|
|
return ret;
|
2008-05-11 22:42:53 +00:00
|
|
|
}
|