#include #include #include 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 (); }