diff --git a/steam-runtime-tools/glib-backports-internal.h b/steam-runtime-tools/glib-backports-internal.h index 805f2ef099a1584579a12e3c3a835173556968ad..21420ba506f09b06b15b202bef4c082da32f7aa9 100644 --- a/steam-runtime-tools/glib-backports-internal.h +++ b/steam-runtime-tools/glib-backports-internal.h @@ -114,3 +114,9 @@ gpointer *my_g_hash_table_get_keys_as_array (GHashTable *hash, #define G_DBUS_METHOD_INVOCATION_HANDLED TRUE #define G_DBUS_METHOD_INVOCATION_UNHANDLED FALSE #endif + +#if !GLIB_CHECK_VERSION(2, 52, 0) +#define g_utf8_make_valid(s,l) my_g_utf8_make_valid (s, l) +gchar *my_g_utf8_make_valid (const gchar *str, + gssize len); +#endif diff --git a/steam-runtime-tools/glib-backports.c b/steam-runtime-tools/glib-backports.c index 2d637a3e6aef11cd6313693daf7289b49272f635..8b2a5103f2b4b3a02f43046af7cba8d651db3cb1 100644 --- a/steam-runtime-tools/glib-backports.c +++ b/steam-runtime-tools/glib-backports.c @@ -510,3 +510,50 @@ my_g_hash_table_get_keys_as_array (GHashTable *hash, return g_ptr_array_free (arr, FALSE); } #endif + +#if !GLIB_CHECK_VERSION(2, 52, 0) +gchar * +my_g_utf8_make_valid (const gchar *str, + gssize len) +{ + GString *string; + const gchar *remainder, *invalid; + gsize remaining_bytes, valid_bytes; + + g_return_val_if_fail (str != NULL, NULL); + + if (len < 0) + len = strlen (str); + + string = NULL; + remainder = str; + remaining_bytes = len; + + while (remaining_bytes != 0) + { + if (g_utf8_validate (remainder, remaining_bytes, &invalid)) + break; + valid_bytes = invalid - remainder; + + if (string == NULL) + string = g_string_sized_new (remaining_bytes); + + g_string_append_len (string, remainder, valid_bytes); + /* append U+FFFD REPLACEMENT CHARACTER */ + g_string_append (string, "\357\277\275"); + + remaining_bytes -= valid_bytes + 1; + remainder = invalid + 1; + } + + if (string == NULL) + return g_strndup (str, len); + + g_string_append_len (string, remainder, remaining_bytes); + g_string_append_c (string, '\0'); + + g_assert (g_utf8_validate (string->str, -1, NULL)); + + return g_string_free (string, FALSE); +} +#endif diff --git a/steam-runtime-tools/json-utils-internal.h b/steam-runtime-tools/json-utils-internal.h new file mode 100644 index 0000000000000000000000000000000000000000..318290e1b4d7d82f7df4ce8c2bc8445257922225 --- /dev/null +++ b/steam-runtime-tools/json-utils-internal.h @@ -0,0 +1,48 @@ +/*<private_header>*/ +/* + * Copyright © 2019-2020 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include <stdio.h> + +#include <glib.h> + +#include <json-glib/json-glib.h> + +#include <steam-runtime-tools/macros.h> + +_SRT_PRIVATE_EXPORT +guint srt_get_flags_from_json_array (GType flags_type, + JsonObject *json_obj, + const gchar *array_member, + guint flag_if_unknown); + +gchar ** _srt_json_object_dup_strv_member (JsonObject *json_obj, + const gchar *array_member, + const gchar *placeholder); + +gchar *_srt_json_object_dup_array_of_lines_member (JsonObject *json_obj, + const gchar *array_member); diff --git a/steam-runtime-tools/json-utils.c b/steam-runtime-tools/json-utils.c new file mode 100644 index 0000000000000000000000000000000000000000..10dfbc7f04b318812130cce618377bf2246236a7 --- /dev/null +++ b/steam-runtime-tools/json-utils.c @@ -0,0 +1,194 @@ +/* + * Copyright © 2019-2020 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "steam-runtime-tools/json-utils-internal.h" + +#include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/utils-internal.h" + +/** + * srt_get_flags_from_json_array: + * @flags_type: The type of the flag + * @json_obj: (not nullable): A JSON Object used to search for + * @array_member property + * @array_member: (not nullable): The JSON member to look up + * @flag_if_unknown: flag to use in case of parsing error + * + * Get the flags from a given JSON object array member. + * If @json_obj doesn't have the provided @member, or it is malformed, the + * @flag_if_unknown will be returned. + * If the parsed JSON array_member has some elements that we can't parse, + * @flag_if_unknown will be added to the returned flags. + * + * Returns: the found flags from the provided @json_obj + */ +guint +srt_get_flags_from_json_array (GType flags_type, + JsonObject *json_obj, + const gchar *array_member, + guint flag_if_unknown) +{ + JsonArray *array; + guint ret = flag_if_unknown; + + g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), 0); + g_return_val_if_fail (json_obj != NULL, 0); + g_return_val_if_fail (array_member != NULL, 0); + + if (json_object_has_member (json_obj, array_member)) + { + array = json_object_get_array_member (json_obj, array_member); + + if (array == NULL) + goto out; + + /* We reset the value out because we found the member we were looking for */ + ret = 0; + + for (guint j = 0; j < json_array_get_length (array); j++) + { + const gchar *issue_string = json_array_get_string_element (array, j); + if (!srt_add_flag_from_nick (flags_type, issue_string, &ret, NULL)) + ret |= flag_if_unknown; + } + } + +out: + return ret; +} + +/** + * _srt_json_object_dup_strv_member: + * @json_obj: (not nullable): A JSON Object used to search for + * @array_member property + * @array_member: (not nullable): The JSON member to look up + * @placeholder: (nullable): If an item in the array is not a string, + * substitute this non-%NULL value; or if %NULL, behave as though it + * was not present + * + * Returns: (transfer full) (array zero-terminated=1) (element-type utf8) (nullable): + * A string array from the given @json_obj, or %NULL if it doesn't have a + * property @array_member + */ +gchar ** +_srt_json_object_dup_strv_member (JsonObject *json_obj, + const gchar *array_member, + const gchar *placeholder) +{ + JsonArray *array; + JsonNode *arr_node; + guint length; + gchar **ret = NULL; + + g_return_val_if_fail (json_obj != NULL, NULL); + g_return_val_if_fail (array_member != NULL, NULL); + + arr_node = json_object_get_member (json_obj, array_member); + + if (arr_node != NULL && JSON_NODE_HOLDS_ARRAY (arr_node)) + { + guint j = 0; + + array = json_node_get_array (arr_node); + + if (array == NULL) + return ret; + + length = json_array_get_length (array); + ret = g_new0 (gchar *, length + 1); + + for (guint i = 0; i < length; i++) + { + JsonNode *node = json_array_get_element (array, i); + const gchar *element = json_node_get_string (node); + + if (element == NULL) + element = placeholder; + + if (element == NULL) + continue; + + ret[j++] = g_strdup (element); + } + + g_assert (j <= length); + ret[j] = NULL; + } + + return ret; +} + +/** + * _srt_json_object_dup_array_of_lines_member: + * @json_obj: (not nullable): A JSON Object used to search for + * @array_member property + * @array_member: (not nullable): The JSON member to look up + * + * If @json_obj has a member named @array_member and it is an array + * of strings, concatenate the strings (adding a trailing newline to + * each one if not already present) and return them. Otherwise, + * return %NULL. + * + * Returns: (transfer full) (element-type utf8) (nullable): + * A string, or %NULL if not found. Free with g_free(). + */ +gchar * +_srt_json_object_dup_array_of_lines_member (JsonObject *json_obj, + const gchar *array_member) +{ + JsonArray *array; + JsonNode *arr_node; + guint length; + g_autoptr(GString) ret = g_string_new (""); + + g_return_val_if_fail (json_obj != NULL, NULL); + g_return_val_if_fail (array_member != NULL, NULL); + + arr_node = json_object_get_member (json_obj, array_member); + + if (arr_node == NULL || !JSON_NODE_HOLDS_ARRAY (arr_node)) + return NULL; + + array = json_node_get_array (arr_node); + + if (array == NULL) + return NULL; + + length = json_array_get_length (array); + + for (guint i = 0; i < length; i++) + { + JsonNode *node = json_array_get_element (array, i); + const gchar *element = json_node_get_string (node); + + if (element != NULL) + g_string_append (ret, element); + + if (element == NULL || element[strlen (element) - 1] != '\n') + g_string_append_c (ret, '\n'); + } + + return g_string_free (g_steal_pointer (&ret), FALSE); +} diff --git a/steam-runtime-tools/library.c b/steam-runtime-tools/library.c index a09c181490e903051aeafd4d0912a6cba93852f7..e77694aaff7af4aab8d51e0f19da38ecf4487c57 100644 --- a/steam-runtime-tools/library.c +++ b/steam-runtime-tools/library.c @@ -29,6 +29,7 @@ #include "steam-runtime-tools/enums.h" #include "steam-runtime-tools/glib-backports-internal.h" #include "steam-runtime-tools/json-glib-backports-internal.h" +#include "steam-runtime-tools/json-utils-internal.h" #include "steam-runtime-tools/library-internal.h" #include "steam-runtime-tools/utils.h" #include "steam-runtime-tools/utils-internal.h" diff --git a/steam-runtime-tools/locale.c b/steam-runtime-tools/locale.c index 8e46d9eb61027042d46011e3837f1637380492f6..4bc7249d0669c81761a2ab1b923717e0f584ab17 100644 --- a/steam-runtime-tools/locale.c +++ b/steam-runtime-tools/locale.c @@ -29,6 +29,7 @@ #include "steam-runtime-tools/enums.h" #include "steam-runtime-tools/glib-backports-internal.h" #include "steam-runtime-tools/json-glib-backports-internal.h" +#include "steam-runtime-tools/json-utils-internal.h" #include "steam-runtime-tools/locale-internal.h" #include "steam-runtime-tools/utils-internal.h" diff --git a/steam-runtime-tools/meson.build b/steam-runtime-tools/meson.build index 964a56fce530d7dc528baeb04ee8a934469729fc..6c0acce1c1f5ecc6f5a60ad4595b13942f88d6c4 100644 --- a/steam-runtime-tools/meson.build +++ b/steam-runtime-tools/meson.build @@ -34,6 +34,8 @@ libsteamrt_sources = [ 'graphics.c', 'json-glib-backports.c', 'json-glib-backports-internal.h', + 'json-utils.c', + 'json-utils-internal.h', 'library-internal.h', 'library.c', 'locale-internal.h', diff --git a/steam-runtime-tools/runtime.c b/steam-runtime-tools/runtime.c index be908f2e3b7a297be6a10177b91558669614e04e..0cdd35405a250b3e1c1321af98316ad371b5a829 100644 --- a/steam-runtime-tools/runtime.c +++ b/steam-runtime-tools/runtime.c @@ -37,6 +37,7 @@ #include <glib/gstdio.h> #include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/json-utils-internal.h" #include "steam-runtime-tools/utils.h" /** diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c index fef92aba2b1cf023f4c2a6f6b03b8fcc5269b4be..2928a68e0b7b264bd7a5578218fb7b6b99715d3b 100644 --- a/steam-runtime-tools/system-info.c +++ b/steam-runtime-tools/system-info.c @@ -36,6 +36,7 @@ #include "steam-runtime-tools/desktop-entry-internal.h" #include "steam-runtime-tools/graphics.h" #include "steam-runtime-tools/graphics-internal.h" +#include "steam-runtime-tools/json-utils-internal.h" #include "steam-runtime-tools/library-internal.h" #include "steam-runtime-tools/locale-internal.h" #include "steam-runtime-tools/os-internal.h" @@ -1348,9 +1349,13 @@ _srt_system_info_get_pinned_libs_from_report (JsonObject *json_obj, { json_pinned_obj = json_object_get_object_member (json_obj, which); - pinned_list = _srt_json_array_to_strv (json_pinned_obj, "list"); + pinned_list = _srt_json_object_dup_strv_member (json_pinned_obj, + "list", + "<invalid>"); - *messages = _srt_json_array_to_strv (json_pinned_obj, "messages"); + *messages = _srt_json_object_dup_strv_member (json_pinned_obj, + "messages", + "<invalid>"); } return pinned_list; @@ -3231,7 +3236,9 @@ srt_system_info_list_driver_environment (SrtSystemInfo *self) static gchar ** _srt_system_info_driver_environment_from_report (JsonObject *json_obj) { - return _srt_json_array_to_strv (json_obj, "driver_environment"); + return _srt_json_object_dup_strv_member (json_obj, + "driver_environment", + "<invalid>"); } typedef struct diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h index 3609b4b888b1a59be2734f4fda56ea2232f134e5..3a7f0fba5871441d952de90dd25b7b23d188cc4d 100644 --- a/steam-runtime-tools/utils-internal.h +++ b/steam-runtime-tools/utils-internal.h @@ -30,8 +30,6 @@ #include <glib.h> -#include <json-glib/json-glib.h> - #include <steam-runtime-tools/macros.h> typedef enum @@ -73,12 +71,6 @@ gboolean srt_add_flag_from_nick (GType flags_type, guint *value_out, GError **error); -_SRT_PRIVATE_EXPORT -guint srt_get_flags_from_json_array (GType flags_type, - JsonObject *json_obj, - const gchar *array_member, - guint flag_if_unknown); - G_GNUC_INTERNAL void _srt_child_setup_unblock_signals (gpointer ignored); _SRT_PRIVATE_EXPORT @@ -87,9 +79,6 @@ void _srt_unblock_signals (void); G_GNUC_INTERNAL int _srt_indirect_strcmp0 (gconstpointer left, gconstpointer right); -gchar ** _srt_json_array_to_strv (JsonObject *json_obj, - const gchar *array_member); - _SRT_PRIVATE_EXPORT gboolean _srt_rm_rf (const char *directory); diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c index a52f07947597aeb20efa87b3dc3fa024715be6a9..074a8ad3b19daec307893830f3e7938f097554f2 100644 --- a/steam-runtime-tools/utils.c +++ b/steam-runtime-tools/utils.c @@ -573,57 +573,6 @@ srt_add_flag_from_nick (GType flags_type, return result; } -/** - * srt_get_flags_from_json_array: - * @flags_type: The type of the flag - * @json_obj: (not nullable): A JSON Object used to search for - * @array_member property - * @array_member: (not nullable): The JSON member to look up - * @flag_if_unknown: flag to use in case of parsing error - * - * Get the flags from a given JSON object array member. - * If @json_obj doesn't have the provided @member, or it is malformed, the - * @flag_if_unknown will be returned. - * If the parsed JSON array_member has some elements that we can't parse, - * @flag_if_unknown will be added to the returned flags. - * - * Returns: the found flags from the provided @json_obj - */ -guint -srt_get_flags_from_json_array (GType flags_type, - JsonObject *json_obj, - const gchar *array_member, - guint flag_if_unknown) -{ - JsonArray *array; - guint ret = flag_if_unknown; - - g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), 0); - g_return_val_if_fail (json_obj != NULL, 0); - g_return_val_if_fail (array_member != NULL, 0); - - if (json_object_has_member (json_obj, array_member)) - { - array = json_object_get_array_member (json_obj, array_member); - - if (array == NULL) - goto out; - - /* We reset the value out because we found the member we were looking for */ - ret = 0; - - for (guint j = 0; j < json_array_get_length (array); j++) - { - const gchar *issue_string = json_array_get_string_element (array, j); - if (!srt_add_flag_from_nick (flags_type, issue_string, &ret, NULL)) - ret |= flag_if_unknown; - } - } - -out: - return ret; -} - static void _srt_constructor (void) __attribute__((__constructor__)); static void _srt_constructor (void) @@ -787,52 +736,6 @@ _srt_rm_rf (const char *directory) return TRUE; } -/** - * _srt_json_array_to_strv: - * @json_obj: (not nullable): A JSON Object used to search for - * @array_member property - * @array_member: (not nullable): The JSON member to look up - * - * Every %NULL or non string members of the array are replaced with the value - * "<invalid>". - * - * Returns: (transfer full) (array zero-terminated=1) (element-type utf8) (nullable): - * A string array from the given @json_obj, or %NULL if it doesn't have a - * property @array_member - */ -gchar ** -_srt_json_array_to_strv (JsonObject *json_obj, - const gchar *array_member) -{ - JsonArray *array; - guint length; - const gchar *element; - gchar **ret = NULL; - - g_return_val_if_fail (json_obj != NULL, NULL); - g_return_val_if_fail (array_member != NULL, NULL); - - if (json_object_has_member (json_obj, array_member)) - { - array = json_object_get_array_member (json_obj, array_member); - if (array == NULL) - return ret; - - length = json_array_get_length (array); - ret = g_new0 (gchar *, length + 1); - for (guint i = 0; i < length; i++) - { - element = json_array_get_string_element (array, i); - if (element == NULL) - element = "<invalid>"; - ret[i] = g_strdup (element); - } - ret[length] = NULL; - } - - return ret; -} - /* * _srt_divert_stdout_to_stderr: * @error: Used to raise an error on failure diff --git a/steam-runtime-tools/xdg-portal.c b/steam-runtime-tools/xdg-portal.c index 5c32df417370036bcc476f95588bd02015913d4f..fb3c56a950fdec881d84c1bbb149da4c0057d02c 100644 --- a/steam-runtime-tools/xdg-portal.c +++ b/steam-runtime-tools/xdg-portal.c @@ -28,6 +28,7 @@ #include "steam-runtime-tools/enums.h" #include "steam-runtime-tools/glib-backports-internal.h" #include "steam-runtime-tools/json-glib-backports-internal.h" +#include "steam-runtime-tools/json-utils-internal.h" #include "steam-runtime-tools/xdg-portal-internal.h" #include "steam-runtime-tools/utils.h" #include "steam-runtime-tools/utils-internal.h" diff --git a/tests/json-utils.c b/tests/json-utils.c new file mode 100644 index 0000000000000000000000000000000000000000..6044a425e177138023f8c70dc15e064f3e7450dc --- /dev/null +++ b/tests/json-utils.c @@ -0,0 +1,147 @@ +/* + * Copyright © 2019-2020 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <steam-runtime-tools/steam-runtime-tools.h> + +#include <glib.h> +#include <glib/gstdio.h> +#include <glib-object.h> + +#include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/json-glib-backports-internal.h" +#include "steam-runtime-tools/json-utils-internal.h" + +typedef struct +{ + int unused; +} Fixture; + +typedef struct +{ + int unused; +} Config; + +static void +setup (Fixture *f, + gconstpointer context) +{ + G_GNUC_UNUSED const Config *config = context; +} + +static void +teardown (Fixture *f, + gconstpointer context) +{ + G_GNUC_UNUSED const Config *config = context; +} + +static void +test_dup_array_of_lines_member (Fixture *f, + gconstpointer context) +{ + g_autoptr(JsonArray) arr = json_array_new (); + g_autoptr(JsonNode) arr_node = json_node_alloc (); + g_autoptr(JsonObject) obj = json_object_new (); + g_autofree gchar *missing = NULL; + g_autofree gchar *not_array = NULL; + g_autofree gchar *text = NULL; + + json_array_add_string_element (arr, "one"); + json_array_add_string_element (arr, "two\n"); + json_array_add_object_element (arr, json_object_new ()); + json_array_add_string_element (arr, "four"); + json_node_init_array (arr_node, arr); + json_object_set_member (obj, "arr", g_steal_pointer (&arr_node)); + json_object_set_double_member (obj, "not-array", 42.0); + + missing = _srt_json_object_dup_array_of_lines_member (obj, "missing"); + g_assert_null (missing); + + not_array = _srt_json_object_dup_array_of_lines_member (obj, "not-array"); + g_assert_null (not_array); + + text = _srt_json_object_dup_array_of_lines_member (obj, "arr"); + g_assert_cmpstr (text, ==, + "one\n" + "two\n" + "\n" + "four\n"); +} + +static void +test_dup_strv_member (Fixture *f, + gconstpointer context) +{ + g_autoptr(JsonArray) arr = json_array_new (); + g_autoptr(JsonNode) arr_node = json_node_alloc (); + g_autoptr(JsonObject) obj = json_object_new (); + g_autoptr(JsonObject) empty = json_object_new (); + g_auto(GStrv) missing = NULL; + g_auto(GStrv) not_array = NULL; + g_auto(GStrv) with_placeholder = NULL; + g_auto(GStrv) without_placeholder = NULL; + + json_array_add_string_element (arr, "one"); + json_array_add_string_element (arr, "two"); + json_array_add_object_element (arr, g_steal_pointer (&empty)); + json_array_add_string_element (arr, "four"); + json_node_init_array (arr_node, arr); + json_object_set_member (obj, "arr", g_steal_pointer (&arr_node)); + json_object_set_double_member (obj, "not-array", 42.0); + + missing = _srt_json_object_dup_strv_member (obj, "missing", NULL); + g_assert_null (missing); + + not_array = _srt_json_object_dup_strv_member (obj, "not-array", NULL); + g_assert_null (not_array); + + with_placeholder = _srt_json_object_dup_strv_member (obj, "arr", "?!"); + g_assert_nonnull (with_placeholder); + g_assert_cmpstr (with_placeholder[0], ==, "one"); + g_assert_cmpstr (with_placeholder[1], ==, "two"); + g_assert_cmpstr (with_placeholder[2], ==, "?!"); + g_assert_cmpstr (with_placeholder[3], ==, "four"); + g_assert_cmpstr (with_placeholder[4], ==, NULL); + + without_placeholder = _srt_json_object_dup_strv_member (obj, "arr", NULL); + g_assert_nonnull (without_placeholder); + g_assert_cmpstr (without_placeholder[0], ==, "one"); + g_assert_cmpstr (without_placeholder[1], ==, "two"); + g_assert_cmpstr (without_placeholder[2], ==, "four"); + g_assert_cmpstr (without_placeholder[3], ==, NULL); +} + +int +main (int argc, + char **argv) +{ + g_test_init (&argc, &argv, NULL); + g_test_add ("/json-utils/dup-array-of-lines-member", Fixture, NULL, + setup, test_dup_array_of_lines_member, teardown); + g_test_add ("/json-utils/dup-strv-member", Fixture, NULL, + setup, test_dup_strv_member, teardown); + + return g_test_run (); +} diff --git a/tests/meson.build b/tests/meson.build index 84e24153020712d2beebf37eaea2dea76a3e0072..b2d5b1db772a355ebc60b5adc754d730136059b9 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -31,6 +31,7 @@ tests = [ {'name': 'architecture'}, {'name': 'desktop-entry'}, {'name': 'graphics'}, + {'name': 'json-utils', 'static': true}, {'name': 'library'}, {'name': 'locale'}, {'name': 'system-info'},