#include <string.h>
#include <glib.h>
#include <json-glib/json-glib.h>
static const char *test_json =
"{ \"store\": {"
" \"book\": [ "
" { \"category\": \"reference\","
" \"author\": \"Nigel Rees\","
" \"title\": \"Sayings of the Century\","
" \"price\": \"8.95\""
" },"
" { \"category\": \"fiction\","
" \"author\": \"Evelyn Waugh\","
" \"title\": \"Sword of Honour\","
" \"price\": \"12.99\""
" },"
" { \"category\": \"fiction\","
" \"author\": \"Herman Melville\","
" \"title\": \"Moby Dick\","
" \"isbn\": \"0-553-21311-3\","
" \"price\": \"8.99\""
" },"
" { \"category\": \"fiction\","
" \"author\": \"J. R. R. Tolkien\","
" \"title\": \"The Lord of the Rings\","
" \"isbn\": \"0-395-19395-8\","
" \"price\": \"22.99\""
" }"
" ],"
" \"bicycle\": {"
" \"color\": \"red\","
" \"price\": \"19.95\""
" }"
" }"
"}";
static const struct {
const char *desc;
const char *expr;
const char *res;
guint is_valid : 1;
JsonPathError error_code;
} test_expressions[] = {
{
"INVALID: invalid first character",
"/",
NULL,
FALSE,
JSON_PATH_ERROR_INVALID_QUERY,
},
{
"INVALID: Invalid character following root",
"$ponies",
NULL,
FALSE,
JSON_PATH_ERROR_INVALID_QUERY,
},
{
"INVALID: missing member name or wildcard after dot",
"$.store.",
NULL,
FALSE,
JSON_PATH_ERROR_INVALID_QUERY,
},
{
"INVALID: Malformed slice (missing step)",
"$.store.book[0:1:]",
NULL,
FALSE,
JSON_PATH_ERROR_INVALID_QUERY,
},
{
"INVALID: Malformed set",
"$.store.book[0,1~2]",
NULL,
FALSE,
JSON_PATH_ERROR_INVALID_QUERY,
},
{
"INVALID: Malformed array notation",
"${'store'}",
NULL,
FALSE,
JSON_PATH_ERROR_INVALID_QUERY,
},
{
"INVALID: Malformed slice (invalid separator)",
"$.store.book[0~2]",
NULL,
FALSE,
JSON_PATH_ERROR_INVALID_QUERY,
},
{
"Title of the first book in the store, using objct notation.",
"$.store.book[0].title",
"[\"Sayings of the Century\"]",
TRUE,
},
{
"Title of the first book in the store, using array notation.",
"$['store']['book'][0]['title']",
"[\"Sayings of the Century\"]",
TRUE,
},
{
"All the authors from the every book.",
"$.store.book[*].author",
"[\"Nigel Rees\",\"Evelyn Waugh\",\"Herman Melville\",\"J. R. R. Tolkien\"]",
TRUE,
},
{
"All the authors.",
"$..author",
"[\"Nigel Rees\",\"Evelyn Waugh\",\"Herman Melville\",\"J. R. R. Tolkien\"]",
TRUE,
},
{
"Everything inside the store.",
"$.store.*",
NULL,
TRUE,
},
{
"All the prices in the store.",
"$.store..price",
"[\"8.95\",\"12.99\",\"8.99\",\"22.99\",\"19.95\"]",
TRUE,
},
{
"The third book.",
"$..book[2]",
"[{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":\"8.99\"}]",
TRUE,
},
{
"The last book.",
"$..book[-1:]",
"[{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":\"22.99\"}]",
TRUE,
},
{
"The first two books.",
"$..book[0,1]",
"[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":\"8.95\"},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":\"12.99\"}]",
TRUE,
},
{
"The first two books, using a slice.",
"$..book[:2]",
"[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":\"8.95\"},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":\"12.99\"}]",
TRUE,
},
{
"All the books.",
"$['store']['book'][*]",
"[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":\"8.95\"},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":\"12.99\"},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":\"8.99\"},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":\"22.99\"}]",
TRUE,
},
{
"All the members of the bicycle object.",
"$.store.bicycle.*",
"[\"red\",\"19.95\"]",
TRUE,
},
{
"The root node.",
"$",
"[{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":\"8.95\"},"
"{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":\"12.99\"},"
"{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":\"8.99\"},"
"{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":\"22.99\"}],"
"\"bicycle\":{\"color\":\"red\",\"price\":\"19.95\"}}}]",
TRUE,
}
};
static void
path_expressions_valid (gconstpointer data)
{
const int index_ = GPOINTER_TO_INT (data);
const char *expr = test_expressions[index_].expr;
const char *desc = test_expressions[index_].desc;
JsonPath *path = json_path_new ();
GError *error = NULL;
if (g_test_verbose ())
g_print ("* %s ('%s')\n", desc, expr);
g_assert (json_path_compile (path, expr, &error));
g_assert_no_error (error);
g_object_unref (path);
}
static void
path_expressions_invalid (gconstpointer data)
{
const int index_ = GPOINTER_TO_INT (data);
const char *expr = test_expressions[index_].expr;
const char *desc = test_expressions[index_].desc;
const JsonPathError code = test_expressions[index_].error_code;
JsonPath *path = json_path_new ();
GError *error = NULL;
if (g_test_verbose ())
g_print ("* %s ('%s')\n", desc, expr);
g_assert (!json_path_compile (path, expr, &error));
g_assert_error (error, JSON_PATH_ERROR, code);
g_object_unref (path);
g_clear_error (&error);
}
static void
path_match (gconstpointer data)
{
const int index_ = GPOINTER_TO_INT (data);
const char *desc = test_expressions[index_].desc;
const char *expr = test_expressions[index_].expr;
const char *res = test_expressions[index_].res;
JsonParser *parser = json_parser_new ();
JsonGenerator *gen = json_generator_new ();
JsonPath *path = json_path_new ();
JsonNode *root;
JsonNode *matches;
char *str;
json_parser_load_from_data (parser, test_json, -1, NULL);
root = json_parser_get_root (parser);
g_assert (json_path_compile (path, expr, NULL));
matches = json_path_match (path, root);
g_assert (JSON_NODE_HOLDS_ARRAY (matches));
json_generator_set_root (gen, matches);
str = json_generator_to_data (gen, NULL);
if (g_test_verbose ())
{
g_print ("* %s ('%s') =>\n"
"- result: %s\n"
"- expected: %s\n",
desc, expr,
str,
res);
}
g_assert_cmpstr (str, ==, res);
g_free (str);
json_node_free (matches);
g_object_unref (parser);
g_object_unref (path);
g_object_unref (gen);
}
int
main (int argc,
char *argv[])
{
int i, j;
g_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=");
for (i = 0, j = 1; i < G_N_ELEMENTS (test_expressions); i++)
{
char *path;
if (!test_expressions[i].is_valid)
continue;
path = g_strdup_printf ("/path/expressions/valid/%d", j++);
g_test_add_data_func (path, GINT_TO_POINTER (i), path_expressions_valid);
g_free (path);
}
for (i = 0, j = 1; i < G_N_ELEMENTS (test_expressions); i++)
{
char *path;
if (test_expressions[i].is_valid)
continue;
path = g_strdup_printf ("/path/expressions/invalid/%d", j++);
g_test_add_data_func (path, GINT_TO_POINTER (i), path_expressions_invalid);
g_free (path);
}
for (i = 0, j = 1; i < G_N_ELEMENTS (test_expressions); i++)
{
char *path;
if (!test_expressions[i].is_valid || test_expressions[i].res == NULL)
continue;
path = g_strdup_printf ("/path/match/%d", j++);
g_test_add_data_func (path, GINT_TO_POINTER (i), path_match);
g_free (path);
}
return g_test_run ();
}