# HG changeset patch # User Gary Kramlich # Date 1736757370 21600 # Node ID 36eba703e2b920dd9202b98e49a1571f37e3f14c # Parent d00a312b1d425fb7b26b7568ceb416a51667d9a9 Add some additional methods to Purple.ProtocolConversation This adds virtual functions for setting the title and description as well as some additional implements methods that we were missing. Testing Done: Ran the tests under valgrind and called in the turtles. Bugs closed: PIDGIN-18026 Reviewed at https://reviews.imfreedom.org/r/3738/ diff -r d00a312b1d42 -r 36eba703e2b9 libpurple/purpleprotocolconversation.c --- a/libpurple/purpleprotocolconversation.c Mon Jan 13 01:22:01 2025 -0600 +++ b/libpurple/purpleprotocolconversation.c Mon Jan 13 02:36:10 2025 -0600 @@ -285,6 +285,26 @@ return FALSE; } +gboolean +purple_protocol_conversation_implements_set_topic(PurpleProtocolConversation *protocol) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + + if(iface->set_topic_async == NULL) { + return FALSE; + } + + if(iface->set_topic_finish == NULL) { + return FALSE; + } + + return TRUE; +} + void purple_protocol_conversation_set_topic_async(PurpleProtocolConversation *protocol, PurpleConversation *conversation, @@ -413,6 +433,26 @@ return FALSE; } +gboolean +purple_protocol_conversation_implements_set_avatar(PurpleProtocolConversation *protocol) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + + if(iface->set_avatar_async == NULL) { + return FALSE; + } + + if(iface->set_avatar_finish == NULL) { + return FALSE; + } + + return TRUE; +} + void purple_protocol_conversation_set_avatar_async(PurpleProtocolConversation *protocol, PurpleConversation *conversation, @@ -532,3 +572,148 @@ G_OBJECT_TYPE_NAME(protocol)); } } + +gboolean +purple_protocol_conversation_implements_set_title(PurpleProtocolConversation *protocol) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface->set_title_async == NULL) { + return FALSE; + } + + if(iface->set_title_finish == NULL) { + return FALSE; + } + + return TRUE; +} + +void +purple_protocol_conversation_set_title_async(PurpleProtocolConversation *protocol, + PurpleConversation *conversation, + const char *title, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol)); + g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface != NULL && iface->set_title_async != NULL) { + iface->set_title_async(protocol, conversation, title, cancellable, + callback, data); + } else { + g_task_report_new_error(G_OBJECT(protocol), callback, data, + purple_protocol_conversation_set_title_async, + PURPLE_PROTOCOL_CONVERSATION_DOMAIN, 0, + "%s does not implement set_title_async", + G_OBJECT_TYPE_NAME(protocol)); + } +} + +gboolean +purple_protocol_conversation_set_title_finish(PurpleProtocolConversation *protocol, + GAsyncResult *result, + GError **error) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE); + + if(g_async_result_is_tagged(result, + purple_protocol_conversation_set_title_async)) + { + return g_task_propagate_boolean(G_TASK(result), error); + } + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface != NULL && iface->set_title_finish != NULL) { + return iface->set_title_finish(protocol, result, error); + } + + g_warning("purple_protocol_conversation_set_title_finish called without " + "calling purple_protocol_conversation_set_title_async"); + + return FALSE; +} + +gboolean +purple_protocol_conversation_implements_set_description(PurpleProtocolConversation *protocol) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface->set_description_async == NULL) { + return FALSE; + } + + if(iface->set_description_finish == NULL) { + return FALSE; + } + + return TRUE; +} + +void +purple_protocol_conversation_set_description_async(PurpleProtocolConversation *protocol, + PurpleConversation *conversation, + const char *description, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol)); + g_return_if_fail(PURPLE_IS_CONVERSATION(conversation)); + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface != NULL && iface->set_description_async != NULL) { + iface->set_description_async(protocol, conversation, description, + cancellable, callback, data); + } else { + g_task_report_new_error(G_OBJECT(protocol), callback, data, + purple_protocol_conversation_set_description_async, + PURPLE_PROTOCOL_CONVERSATION_DOMAIN, 0, + "%s does not implement set_description_async", + G_OBJECT_TYPE_NAME(protocol)); + } +} + +gboolean +purple_protocol_conversation_set_description_finish(PurpleProtocolConversation *protocol, + GAsyncResult *result, + GError **error) +{ + PurpleProtocolConversationInterface *iface = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE); + + if(g_async_result_is_tagged(result, + purple_protocol_conversation_set_description_async)) + { + return g_task_propagate_boolean(G_TASK(result), error); + } + + iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol); + if(iface != NULL && iface->set_description_finish != NULL) { + return iface->set_description_finish(protocol, result, error); + } + + g_warning("purple_protocol_conversation_set_description_finish called " + "without calling " + "purple_protocol_conversation_set_description_async"); + + return FALSE; +} diff -r d00a312b1d42 -r 36eba703e2b9 libpurple/purpleprotocolconversation.h --- a/libpurple/purpleprotocolconversation.h Mon Jan 13 01:22:01 2025 -0600 +++ b/libpurple/purpleprotocolconversation.h Mon Jan 13 02:36:10 2025 -0600 @@ -97,6 +97,12 @@ void (*refresh)(PurpleProtocolConversation *protocol, PurpleConversation *conversation); + void (*set_title_async)(PurpleProtocolConversation *protocol, PurpleConversation *conversation, const char *title, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + gboolean (*set_title_finish)(PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error); + + void (*set_description_async)(PurpleProtocolConversation *protocol, PurpleConversation *conversation, const char *description, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + gboolean (*set_description_finish)(PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error); + /*< private >*/ gpointer reserved[8]; }; @@ -284,6 +290,22 @@ gboolean purple_protocol_conversation_send_message_finish(PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error); /** + * purple_protocol_conversation_implements_set_topic: + * @protocol: the instance + * + * Checks if a protocol implements setting topics. + * + * Checks if @protocol implements [vfunc@ProtocolConversation.set_topic_async] + * and [vfunc@ProtocolConversation.set_topic_finish]. + * + * Returns: true if everything is implemented; otherwise false. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_protocol_conversation_implements_set_topic(PurpleProtocolConversation *protocol); + +/** * purple_protocol_conversation_set_topic_async: * @protocol: The instance. * @conversation: The conversation whose topic to set. @@ -383,6 +405,23 @@ gboolean purple_protocol_conversation_join_channel_finish(PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error); /** + * purple_protocol_conversation_implements_set_avatar: + * @protocol: the instance + * + * Checks if a protocol implements setting avatars. + * + * Checks if @protocol implements + * [vfunc@ProtocolConversation.set_avatar_async] and + * [vfunc@ProtocolConversation.set_avatar_finish]. + * + * Returns: true if everything is implemented; otherwise false. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_protocol_conversation_implements_set_avatar(PurpleProtocolConversation *protocol); + +/** * purple_protocol_conversation_set_avatar_async: * @protocol: The instance. * @conversation: The conversation instance. @@ -478,6 +517,113 @@ PURPLE_AVAILABLE_IN_3_0 void purple_protocol_conversation_refresh(PurpleProtocolConversation *protocol, PurpleConversation *conversation); +/** + * purple_protocol_conversation_implements_set_title: + * @protocol: The instance. + * + * Checks if a protocol implements setting conversation titles. + * + * Checks if @protocol implements [vfunc@ProtocolConversation.set_title_async] + * and [vfunc@ProtocolConversation.set_title_finish]. + * + * Returns: true if everything is implemented; otherwise false. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_protocol_conversation_implements_set_title(PurpleProtocolConversation *protocol); + +/** + * purple_protocol_conversation_set_title_async: + * @protocol: the instance + * @conversation: the conversation instance + * @title: (nullable): the new title + * @cancellable: (nullable): optional GCancellable object + * @callback: (nullable) (scope async): callback to call after the title has + * been set + * @data: (nullable): optional user data to pass to @callback. + * + * Sets the title of a conversation. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +void purple_protocol_conversation_set_title_async(PurpleProtocolConversation *protocol, PurpleConversation *conversation, const char *title, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + +/** + * purple_protocol_conversation_set_title_finish: + * @protocol: the instance + * @result: the [iface@Gio.AsyncResult] from the previous + * [method@ProtocolConversation.set_title_async] call + * @error: Return address for a #GError, or %NULL + * + * Finishes a previous call to + * [method@ProtocolConversation.set_title_async]. This should be called from + * the callback of that function to get the result of whether or not the title + * was set successfully. + * + * Returns: true if the title was set successfully, otherwise false with + * @error possibly set. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_protocol_conversation_set_title_finish(PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error); + +/** + * purple_protocol_conversation_implements_set_description: + * @protocol: The instance. + * + * Checks if a protocol implements setting the description of conversations. + * + * Checks if @protocol implements + * [vfunc@ProtocolConversation.set_description_async] and + * [vfunc@ProtocolConversation.set_description_finish]. + * + * Returns: true if everything is implemented; otherwise false. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_protocol_conversation_implements_set_description(PurpleProtocolConversation *protocol); + +/** + * purple_protocol_conversation_set_description_async: + * @protocol: the instance + * @conversation: the conversation instance + * @description: (nullable): the new description + * @cancellable: (nullable): optional GCancellable object + * @callback: (nullable) (scope async): callback to call after the description + * has been set + * @data: (nullable): optional user data to pass to @callback. + * + * Sets the description of a conversation. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +void purple_protocol_conversation_set_description_async(PurpleProtocolConversation *protocol, PurpleConversation *conversation, const char *description, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + +/** + * purple_protocol_conversation_set_description_finish: + * @protocol: the instance + * @result: the [iface@Gio.AsyncResult] from the previous + * [method@ProtocolConversation.set_description_async] call + * @error: Return address for a #GError, or %NULL + * + * Finishes a previous call to + * [method@ProtocolConversation.set_description_async]. This should be called + * from the callback of that function to get the result of whether or not the + * description was set successfully. + * + * Returns: true if the description was set successfully, otherwise false with + * @error possibly set. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +gboolean purple_protocol_conversation_set_description_finish(PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error); + G_END_DECLS #endif /* PURPLE_PROTOCOL_CONVERSATION_H */ diff -r d00a312b1d42 -r 36eba703e2b9 libpurple/tests/test_protocol_conversation.c --- a/libpurple/tests/test_protocol_conversation.c Mon Jan 13 01:22:01 2025 -0600 +++ b/libpurple/tests/test_protocol_conversation.c Mon Jan 13 02:36:10 2025 -0600 @@ -283,6 +283,18 @@ } static void +test_purple_protocol_conversation_empty_implements_set_topic(void) { + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + + g_assert_false(purple_protocol_conversation_implements_set_topic(protocol)); + + g_assert_finalize_object(protocol); +} + +static void test_purple_protocol_conversation_empty_set_topic_async(void) { PurpleAccount *account = NULL; PurpleConversation *conversation = NULL; @@ -375,6 +387,18 @@ } static void +test_purple_protocol_conversation_empty_implements_set_avatar(void) { + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + + g_assert_false(purple_protocol_conversation_implements_set_avatar(protocol)); + + g_assert_finalize_object(protocol); +} + +static void test_purple_protocol_conversation_empty_set_avatar_cb(GObject *source, GAsyncResult *result, G_GNUC_UNUSED gpointer data) @@ -497,6 +521,118 @@ g_test_trap_assert_stderr("*Purple-WARNING*TestPurpleProtocolConversationEmpty*refresh*"); } +static void +test_purple_protocol_conversation_empty_implements_set_title(void) { + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + + g_assert_false(purple_protocol_conversation_implements_set_title(protocol)); + + g_assert_finalize_object(protocol); +} + +static void +test_purple_protocol_conversation_empty_set_title_cb(GObject *source, + GAsyncResult *result, + G_GNUC_UNUSED gpointer data) +{ + PurpleProtocolConversation *protocol = NULL; + GError *error = NULL; + gboolean set = FALSE; + + protocol = PURPLE_PROTOCOL_CONVERSATION(source); + set = purple_protocol_conversation_set_title_finish(protocol, result, + &error); + g_assert_error(error, PURPLE_PROTOCOL_CONVERSATION_DOMAIN, 0); + g_clear_error(&error); + g_assert_false(set); +} + +static void +test_purple_protocol_conversation_empty_set_title_async(void) { + PurpleAccount *account = NULL; + PurpleConversation *conversation = NULL; + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + purple_protocol_conversation_set_title_async(protocol, conversation, + "title", NULL, + test_purple_protocol_conversation_empty_set_title_cb, + NULL); + + g_main_context_iteration(NULL, FALSE); + + g_clear_object(&account); + g_assert_finalize_object(conversation); + g_assert_finalize_object(protocol); +} + +static void +test_purple_protocol_conversation_empty_implements_set_description(void) { + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + + g_assert_false(purple_protocol_conversation_implements_set_description(protocol)); + + g_assert_finalize_object(protocol); +} + +static void +test_purple_protocol_conversation_empty_set_description_cb(GObject *source, + GAsyncResult *result, + G_GNUC_UNUSED gpointer data) +{ + PurpleProtocolConversation *protocol = NULL; + GError *error = NULL; + gboolean set = FALSE; + + protocol = PURPLE_PROTOCOL_CONVERSATION(source); + set = purple_protocol_conversation_set_description_finish(protocol, result, + &error); + g_assert_error(error, PURPLE_PROTOCOL_CONVERSATION_DOMAIN, 0); + g_clear_error(&error); + g_assert_false(set); +} + +static void +test_purple_protocol_conversation_empty_set_description_async(void) { + PurpleAccount *account = NULL; + PurpleConversation *conversation = NULL; + PurpleProtocolConversation *protocol = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(), + NULL); + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + purple_protocol_conversation_set_description_async(protocol, conversation, + "description", NULL, + test_purple_protocol_conversation_empty_set_description_cb, + NULL); + + g_main_context_iteration(NULL, FALSE); + + g_clear_object(&account); + g_assert_finalize_object(conversation); + g_assert_finalize_object(protocol); +} + /****************************************************************************** * TestProtocolConversation Implementation *****************************************************************************/ @@ -531,6 +667,12 @@ guint send_typing; guint refresh; + + guint set_title_async; + guint set_title_finish; + + guint set_description_async; + guint set_description_finish; }; static PurpleCreateConversationDetails * @@ -848,6 +990,88 @@ } static void +test_purple_protocol_conversation_set_title_async(PurpleProtocolConversation *protocol, + PurpleConversation *conversation, + G_GNUC_UNUSED const char *title, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + TestPurpleProtocolConversation *test_protocol = NULL; + GTask *task = NULL; + + g_assert_true(PURPLE_IS_CONVERSATION(conversation)); + + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(protocol); + test_protocol->set_title_async += 1; + + task = g_task_new(protocol, cancellable, callback, data); + if(test_protocol->should_error) { + g_task_return_new_error_literal(task, + TEST_PURPLE_PROTOCOL_CONVERSATION_DOMAIN, + 0, "error"); + } else { + g_task_return_boolean(task, TRUE); + } + + g_clear_object(&task); +} + +static gboolean +test_purple_protocol_conversation_set_title_finish(PurpleProtocolConversation *protocol, + GAsyncResult *result, + GError **error) +{ + TestPurpleProtocolConversation *test_protocol = NULL; + + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(protocol); + test_protocol->set_title_finish += 1; + + return g_task_propagate_boolean(G_TASK(result), error); +} + +static void +test_purple_protocol_conversation_set_description_async(PurpleProtocolConversation *protocol, + PurpleConversation *conversation, + G_GNUC_UNUSED const char *description, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + TestPurpleProtocolConversation *test_protocol = NULL; + GTask *task = NULL; + + g_assert_true(PURPLE_IS_CONVERSATION(conversation)); + + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(protocol); + test_protocol->set_description_async += 1; + + task = g_task_new(protocol, cancellable, callback, data); + if(test_protocol->should_error) { + g_task_return_new_error_literal(task, + TEST_PURPLE_PROTOCOL_CONVERSATION_DOMAIN, + 0, "error"); + } else { + g_task_return_boolean(task, TRUE); + } + + g_clear_object(&task); +} + +static gboolean +test_purple_protocol_conversation_set_description_finish(PurpleProtocolConversation *protocol, + GAsyncResult *result, + GError **error) +{ + TestPurpleProtocolConversation *test_protocol = NULL; + + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(protocol); + test_protocol->set_description_finish += 1; + + return g_task_propagate_boolean(G_TASK(result), error); +} + +static void test_purple_protocol_conversation_iface_init(PurpleProtocolConversationInterface *iface) { iface->get_create_conversation_details = test_purple_protocol_conversation_get_create_conversation_details; iface->create_conversation_async = test_purple_protocol_conversation_create_conversation_async; @@ -871,6 +1095,12 @@ iface->send_typing = test_purple_protocol_conversation_send_typing; iface->refresh = test_purple_protocol_conversation_refresh; + + iface->set_title_async = test_purple_protocol_conversation_set_title_async; + iface->set_title_finish = test_purple_protocol_conversation_set_title_finish; + + iface->set_description_async = test_purple_protocol_conversation_set_description_async; + iface->set_description_finish = test_purple_protocol_conversation_set_description_finish; } G_DEFINE_FINAL_TYPE_WITH_CODE(TestPurpleProtocolConversation, @@ -904,6 +1134,12 @@ protocol->send_typing = 0; protocol->refresh = 0; + + protocol->set_title_async = 0; + protocol->set_title_finish = 0; + + protocol->set_description_async = 0; + protocol->set_description_finish = 0; } static void @@ -1460,6 +1696,129 @@ } /****************************************************************************** + * TestProtocolConversation set_title Tests + *****************************************************************************/ +static void +test_purple_protocol_conversation_set_title_cb(GObject *obj, + GAsyncResult *res, + G_GNUC_UNUSED gpointer data) +{ + TestPurpleProtocolConversation *test_protocol = NULL; + PurpleProtocolConversation *protocol = NULL; + GError *error = NULL; + gboolean result = FALSE; + + protocol = PURPLE_PROTOCOL_CONVERSATION(obj); + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(obj); + + result = purple_protocol_conversation_set_title_finish(protocol, res, + &error); + + if(test_protocol->should_error) { + g_assert_error(error, TEST_PURPLE_PROTOCOL_CONVERSATION_DOMAIN, 0); + g_clear_error(&error); + g_assert_false(result); + } else { + g_assert_no_error(error); + g_assert_true(result); + } +} + +static void +test_purple_protocol_conversation_set_title_normal(gconstpointer data) { + TestPurpleProtocolConversation *protocol = NULL; + PurpleAccount *account = NULL; + PurpleConversation *conversation = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_get_type(), + NULL); + protocol->should_error = GPOINTER_TO_INT(data); + + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + purple_protocol_conversation_set_title_async(PURPLE_PROTOCOL_CONVERSATION(protocol), + conversation, "title", NULL, + test_purple_protocol_conversation_set_title_cb, + NULL); + + g_main_context_iteration(NULL, FALSE); + + g_assert_cmpuint(protocol->set_title_async, ==, 1); + g_assert_cmpuint(protocol->set_title_finish, ==, 1); + + g_assert_finalize_object(conversation); + g_assert_finalize_object(protocol); + g_clear_object(&account); +} + +/****************************************************************************** + * TestProtocolConversation set_description Tests + *****************************************************************************/ +static void +test_purple_protocol_conversation_set_description_cb(GObject *obj, + GAsyncResult *res, + G_GNUC_UNUSED gpointer data) +{ + TestPurpleProtocolConversation *test_protocol = NULL; + PurpleProtocolConversation *protocol = NULL; + GError *error = NULL; + gboolean result = FALSE; + + protocol = PURPLE_PROTOCOL_CONVERSATION(obj); + test_protocol = TEST_PURPLE_PROTOCOL_CONVERSATION(obj); + + result = purple_protocol_conversation_set_description_finish(protocol, res, + &error); + + if(test_protocol->should_error) { + g_assert_error(error, TEST_PURPLE_PROTOCOL_CONVERSATION_DOMAIN, 0); + g_clear_error(&error); + g_assert_false(result); + } else { + g_assert_no_error(error); + g_assert_true(result); + } +} + +static void +test_purple_protocol_conversation_set_description_normal(gconstpointer data) { + TestPurpleProtocolConversation *protocol = NULL; + PurpleAccount *account = NULL; + PurpleConversation *conversation = NULL; + + protocol = g_object_new(test_purple_protocol_conversation_get_type(), + NULL); + protocol->should_error = GPOINTER_TO_INT(data); + + account = purple_account_new("test", "test"); + conversation = g_object_new( + PURPLE_TYPE_CONVERSATION, + "account", account, + "type", PURPLE_CONVERSATION_TYPE_DM, + NULL); + + purple_protocol_conversation_set_description_async(PURPLE_PROTOCOL_CONVERSATION(protocol), + conversation, + "description", NULL, + test_purple_protocol_conversation_set_description_cb, + NULL); + + g_main_context_iteration(NULL, FALSE); + + g_assert_cmpuint(protocol->set_description_async, ==, 1); + g_assert_cmpuint(protocol->set_description_finish, ==, 1); + + g_assert_finalize_object(conversation); + g_assert_finalize_object(protocol); + g_clear_object(&account); +} + +/****************************************************************************** * Main *****************************************************************************/ gint @@ -1488,8 +1847,13 @@ g_test_add_func("/protocol-conversation/empty/send-message-async", test_purple_protocol_conversation_empty_send_message_async); + g_test_add_func("/protocol-conversation/empty/implements-set-topic", + test_purple_protocol_conversation_empty_implements_set_topic); g_test_add_func("/protocol-conversation/empty/set-topic-async", test_purple_protocol_conversation_empty_set_topic_async); + + g_test_add_func("/protocol-conversation/empty/implements-set-avatar", + test_purple_protocol_conversation_empty_implements_set_avatar); g_test_add_func("/protocol-conversation/empty/set-avatar-async", test_purple_protocol_conversation_empty_set_avatar_async); @@ -1499,6 +1863,16 @@ g_test_add_func("/protocol-conversation/empty/join_channel_async", test_purple_protocol_conversation_empty_join_channel_async); + g_test_add_func("/protocol-conversation/empty/implements-set-title", + test_purple_protocol_conversation_empty_implements_set_title); + g_test_add_func("/protocol-conversation/empty/set-title-async", + test_purple_protocol_conversation_empty_set_title_async); + + g_test_add_func("/protocol-conversation/empty/implements-set-description", + test_purple_protocol_conversation_empty_implements_set_description); + g_test_add_func("/protocol-conversation/empty/set-description-async", + test_purple_protocol_conversation_empty_set_description_async); + /* Empty send typing tests. */ g_test_add_func("/protocol-conversation/empty/implements-send-typing", test_purple_protocol_conversation_empty_implements_send_typing); @@ -1581,5 +1955,21 @@ g_test_add_func("/protocol-conversation/normal/refresh", test_purple_protocol_conversation_refresh_normal); + /* Normal set title tests. */ + g_test_add_data_func("/protocol-contacts/normal/set-title-normal", + GINT_TO_POINTER(FALSE), + test_purple_protocol_conversation_set_title_normal); + g_test_add_data_func("/protocol-contacts/normal/set-title-error", + GINT_TO_POINTER(TRUE), + test_purple_protocol_conversation_set_title_normal); + + /* Normal set description tests. */ + g_test_add_data_func("/protocol-contacts/normal/set-description-normal", + GINT_TO_POINTER(FALSE), + test_purple_protocol_conversation_set_description_normal); + g_test_add_data_func("/protocol-contacts/normal/set-description-error", + GINT_TO_POINTER(TRUE), + test_purple_protocol_conversation_set_description_normal); + return g_test_run(); } diff -r d00a312b1d42 -r 36eba703e2b9 meson.build --- a/meson.build Mon Jan 13 01:22:01 2025 -0600 +++ b/meson.build Mon Jan 13 02:36:10 2025 -0600 @@ -171,13 +171,13 @@ ####################################################################### # Check for GLib (required) ####################################################################### -glib = dependency('glib-2.0', version : '>= 2.78.0') +glib = dependency('glib-2.0', version : '>= 2.80.0') gio = dependency('gio-2.0') gnome = import('gnome') add_project_arguments( - '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_78', - '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_78', + '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_80', + '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_80', language : 'c',) #######################################################################