Mon, 13 Jan 2025 02:36:10 -0600
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/
--- 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; +}
--- 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 */
--- 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(); }
--- 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',) #######################################################################