Sat, 09 Aug 2025 17:37:27 +0800
Fix the birb header path
The birb header referred would only work with birb provided by wrap casuing
build to fail because of system-installed birb dependency. The commit points
it to the correct path <birb.h>.
See: https://keep.imfreedom.org/birb/birb/file/5bf00c7d7f80/birb/meson.build#l77
/* * Purple - Internet Messaging Library * Copyright (C) Pidgin Developers <devel@pidgin.im> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <https://www.gnu.org/licenses/>. */ #include <glib.h> #include <purple.h> /****************************************************************************** * Callbacks *****************************************************************************/ static void test_purple_conversation_member_notify_counter(GObject *self, G_GNUC_UNUSED GParamSpec *pspec, gpointer data) { guint *counter = data; g_assert_true(PURPLE_IS_CONVERSATION_MEMBER(self)); *counter = *counter + 1; } static void test_purple_conversation_member_badges_changed_counter(PurpleConversationMember *member, gpointer data) { guint *counter = data; g_assert_true(PURPLE_IS_CONVERSATION_MEMBER(member)); *counter = *counter + 1; } /****************************************************************************** * Tests *****************************************************************************/ static void test_purple_conversation_member_new(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); g_assert_true(PURPLE_IS_CONTACT_INFO(info)); member = purple_conversation_member_new(info); g_assert_true(PURPLE_IS_CONVERSATION_MEMBER(member)); g_clear_object(&info); g_clear_object(&member); } static void test_purple_conversation_member_properties(void) { PurpleBadges *badges = NULL; PurpleContactInfo *info = NULL; PurpleContactInfo *info1 = NULL; PurpleConversationMember *member = NULL; PurpleTags *tags = NULL; PurpleTypingState typing_state = PURPLE_TYPING_STATE_NONE; char *alias = NULL; char *color = NULL; char *name_for_display = NULL; char *nickname = NULL; info = purple_contact_info_new("abc123"); /* Use g_object_new so we can test setting properties by name. All of them * call the setter methods, so by doing it this way we exercise more of the * code. */ member = g_object_new( PURPLE_TYPE_CONVERSATION_MEMBER, "alias", "pidgy1", "color", "#55aaff", "contact-info", info, "nickname", "pidgy", "typing-state", PURPLE_TYPING_STATE_TYPING, NULL); /* Now use g_object_get to read all of the properties. */ g_object_get( member, "alias", &alias, "badges", &badges, "color", &color, "contact-info", &info1, "name-for-display", &name_for_display, "nickname", &nickname, "tags", &tags, "typing-state", &typing_state, NULL); g_assert_cmpstr(alias, ==, "pidgy1"); g_clear_pointer(&alias, g_free); g_assert_true(PURPLE_IS_BADGES(badges)); g_clear_object(&badges); g_assert_cmpstr(color, ==, "#55aaff"); g_clear_pointer(&color, g_free); g_assert_true(info1 == info); g_clear_object(&info1); g_assert_cmpstr(name_for_display, ==, "pidgy1"); g_clear_pointer(&name_for_display, g_free); g_assert_cmpstr(nickname, ==, "pidgy"); g_clear_pointer(&nickname, g_free); g_assert_true(PURPLE_IS_TAGS(tags)); g_clear_object(&tags); g_assert_cmpint(typing_state, ==, PURPLE_TYPING_STATE_TYPING); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_name_for_display(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; const char *name_for_display = NULL; guint counter = 0; info = purple_contact_info_new("abc123"); member = purple_conversation_member_new(info); g_signal_connect(member, "notify::name-for-display", G_CALLBACK(test_purple_conversation_member_notify_counter), &counter); /* Make sure our counter is still 0. */ g_assert_cmpuint(counter, ==, 0); /* Make sure the default falls back to the contact info's id. */ name_for_display = purple_conversation_member_get_name_for_display(member); g_assert_cmpstr(name_for_display, ==, "abc123"); /* Set the username on the contact info and make sure it propagates up. */ counter = 0; purple_contact_info_set_username(info, "tron"); name_for_display = purple_conversation_member_get_name_for_display(member); g_assert_cmpstr(name_for_display, ==, "tron"); g_assert_cmpuint(counter, ==, 1); /* Set the nickname on the conversation member and make sure that takes * precedence. */ counter = 0; purple_conversation_member_set_nickname(member, "rinzler"); name_for_display = purple_conversation_member_get_name_for_display(member); g_assert_cmpstr(name_for_display, ==, "rinzler"); g_assert_cmpuint(counter, ==, 1); /* Set the alias on the conversation member and make sure that takes * precedence. */ counter = 0; purple_conversation_member_set_alias(member, "Alan"); name_for_display = purple_conversation_member_get_name_for_display(member); g_assert_cmpstr(name_for_display, ==, "Alan"); g_assert_cmpuint(counter, ==, 1); /* Remove the alias and verify we fall back to the nickname. */ counter = 0; purple_conversation_member_set_alias(member, NULL); name_for_display = purple_conversation_member_get_name_for_display(member); g_assert_cmpstr(name_for_display, ==, "rinzler"); g_assert_cmpuint(counter, ==, 1); /* Remove the nickname and verify it falls back to the value from the * contact info. */ counter = 0; purple_conversation_member_set_nickname(member, NULL); name_for_display = purple_conversation_member_get_name_for_display(member); g_assert_cmpstr(name_for_display, ==, "tron"); g_assert_cmpuint(counter, ==, 1); g_assert_finalize_object(member); g_assert_finalize_object(info); } /****************************************************************************** * Typing State Timeout *****************************************************************************/ static void test_purple_conversation_manager_timeout_notify(GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, gpointer data) { PurpleConversationMember *member = NULL; PurpleTypingState state = PURPLE_TYPING_STATE_NONE; gboolean *done = data; static guint count = 0; g_assert_true(PURPLE_IS_CONVERSATION_MEMBER(obj)); member = PURPLE_CONVERSATION_MEMBER(obj); state = purple_conversation_member_get_typing_state(member); if(count == 0) { g_assert_cmpuint(state, ==, PURPLE_TYPING_STATE_TYPING); } else if(count == 1) { g_assert_cmpuint(state, ==, PURPLE_TYPING_STATE_NONE); } else { g_assert_not_reached(); } /* Increment count each time we're called. */ count++; if(count >= 2) { *done = TRUE; } } static void test_purple_conversation_member_typing_state_fail_safe(gpointer data) { gboolean *done = data; g_assert_not_reached(); *done = TRUE; } static void test_purple_conversation_member_typing_state_timeout(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; PurpleTypingState typing_state = PURPLE_TYPING_STATE_TYPING; gboolean done = FALSE; /* Create the member and add a notify callback on the typing-state property * so we can check it and exit the main loop. */ info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); g_signal_connect(member, "notify::typing-state", G_CALLBACK(test_purple_conversation_manager_timeout_notify), &done); /* Set the state to typing with a timeout of 1 second. */ purple_conversation_member_set_typing_state(member, PURPLE_TYPING_STATE_TYPING, 1); /* We add a fail safe to set done after 2 seconds. */ g_timeout_add_seconds_once(2, test_purple_conversation_member_typing_state_fail_safe, &done); while(!done) { g_main_context_iteration(NULL, FALSE); } /* Verify that our state got reset back to PURPLE_TYPING_STATE_NONE. */ typing_state = purple_conversation_member_get_typing_state(member); g_assert_cmpint(typing_state, ==, PURPLE_TYPING_STATE_NONE); /* Clean everything up. */ g_clear_object(&info); g_clear_object(&member); } static void test_purple_conversation_member_badges_changed_signal(void) { PurpleBadge *badge = NULL; PurpleBadges *badges = NULL; PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; guint counter = 0; /* Create the member and connect to the badges-changed signal for verify * it was emitted when expected. */ info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); g_signal_connect(member, "badges-changed", G_CALLBACK(test_purple_conversation_member_badges_changed_counter), &counter); badges = purple_conversation_member_get_badges(member); /* Add a badge and verify badges-changed only got emitted once. */ counter = 0; badge = purple_badge_new("test", 0, "test-icon", "t"); purple_badges_add_badge(badges, badge); g_assert_cmpuint(counter, ==, 1); g_clear_object(&badge); /* Remove the badge and verify badges-changed only got emitted once. */ counter = 0; purple_badges_remove_badge(badges, "test"); g_assert_cmpuint(counter, ==, 1); /* Clean everything up. */ g_clear_object(&info); g_clear_object(&member); } /****************************************************************************** * Matches Tests *****************************************************************************/ static void test_purple_conversation_member_matches_accepts_null(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); g_assert_true(purple_conversation_member_matches(member, NULL)); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_matches_empty_string(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); g_assert_true(purple_conversation_member_matches(member, "")); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_matches_alias(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); purple_conversation_member_set_alias(member, "this is the alias"); g_assert_true(purple_conversation_member_matches(member, "the")); g_assert_false(purple_conversation_member_matches(member, "what")); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_matches_nickname(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); purple_conversation_member_set_alias(member, "nickosaurus"); g_assert_true(purple_conversation_member_matches(member, "nick")); g_assert_false(purple_conversation_member_matches(member, "dinosaur")); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_matches_contact_info(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); purple_contact_info_set_alias(info, "something"); member = purple_conversation_member_new(info); g_assert_true(purple_conversation_member_matches(member, "some")); g_assert_false(purple_conversation_member_matches(member, "any")); g_assert_finalize_object(member); g_assert_finalize_object(info); } /****************************************************************************** * Compare Tests *****************************************************************************/ static void test_purple_conversation_member_compare_not_null__null(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); g_assert_cmpint(purple_conversation_member_compare(member, NULL), <, 0); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_compare_null__not_null(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); g_assert_cmpint(purple_conversation_member_compare(NULL, member), >, 0); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_compare_null__null(void) { g_assert_cmpint(purple_conversation_member_compare(NULL, NULL), ==, 0); } static void test_purple_conversation_member_compare_same(void) { PurpleContactInfo *info = NULL; PurpleConversationMember *member = NULL; info = purple_contact_info_new(NULL); member = purple_conversation_member_new(info); g_assert_cmpint(purple_conversation_member_compare(member, member), ==, 0); g_assert_finalize_object(member); g_assert_finalize_object(info); } static void test_purple_conversation_member_compare_nickname__nickname(void) { PurpleContactInfo *info1 = NULL; PurpleContactInfo *info2 = NULL; PurpleConversationMember *member1 = NULL; PurpleConversationMember *member2 = NULL; int result = 0; info1 = purple_contact_info_new(NULL); member1 = purple_conversation_member_new(info1); purple_conversation_member_set_nickname(member1, "aaa"); info2 = purple_contact_info_new(NULL); member2 = purple_conversation_member_new(info2); purple_conversation_member_set_nickname(member2, "zzz"); result = purple_conversation_member_compare(member1, member2); g_assert_cmpint(result, <, 0); result = purple_conversation_member_compare(member2, member1); g_assert_cmpint(result, >, 0); purple_conversation_member_set_nickname(member2, "aaa"); result = purple_conversation_member_compare(member1, member2); g_assert_cmpint(result, ==, 0); g_assert_finalize_object(member1); g_assert_finalize_object(member2); g_assert_finalize_object(info1); g_assert_finalize_object(info2); } static void test_purple_conversation_member_compare_badges__nickname(void) { PurpleBadge *badge = NULL; PurpleBadges *badges = NULL; PurpleContactInfo *info1 = NULL; PurpleContactInfo *info2 = NULL; PurpleConversationMember *member1 = NULL; PurpleConversationMember *member2 = NULL; gboolean removed = FALSE; int result = 0; info1 = purple_contact_info_new(NULL); member1 = purple_conversation_member_new(info1); purple_conversation_member_set_nickname(member1, "zzz"); badges = purple_conversation_member_get_badges(member1); badge = purple_badge_new("id", 1000, "icon", "I"); purple_badges_add_badge(badges, badge); g_clear_object(&badge); info2 = purple_contact_info_new(NULL); member2 = purple_conversation_member_new(info2); purple_conversation_member_set_nickname(member2, "aaa"); result = purple_conversation_member_compare(member1, member2); g_assert_cmpint(result, <, 0); result = purple_conversation_member_compare(member2, member1); g_assert_cmpint(result, >, 0); /* Remove the badge and make sure member2 is sorted first because its * nickname sorts first. */ removed = purple_badges_remove_badge(badges, "id"); g_assert_true(removed); result = purple_conversation_member_compare(member1, member2); g_assert_cmpint(result, >, 0); g_assert_finalize_object(member1); g_assert_finalize_object(member2); g_assert_finalize_object(info1); g_assert_finalize_object(info2); } /****************************************************************************** * Main *****************************************************************************/ int main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); g_test_set_nonfatal_assertions(); g_test_add_func("/conversation-member/new", test_purple_conversation_member_new); g_test_add_func("/conversation-member/properties", test_purple_conversation_member_properties); g_test_add_func("/conversation-member/name-for-display", test_purple_conversation_member_name_for_display); g_test_add_func("/conversation-member/typing-state/timeout", test_purple_conversation_member_typing_state_timeout); g_test_add_func("/conversation-member/badges-changed-signal", test_purple_conversation_member_badges_changed_signal); g_test_add_func("/conversation-member/matches/accepts_null", test_purple_conversation_member_matches_accepts_null); g_test_add_func("/conversation-member/matches/empty_string", test_purple_conversation_member_matches_empty_string); g_test_add_func("/conversation-member/matches/alias", test_purple_conversation_member_matches_alias); g_test_add_func("/conversation-member/matches/nickname", test_purple_conversation_member_matches_nickname); g_test_add_func("/conversation-member/matches/contact_info", test_purple_conversation_member_matches_contact_info); g_test_add_func("/conversation-member/compare/not_null__null", test_purple_conversation_member_compare_not_null__null); g_test_add_func("/conversation-member/compare/null__not_null", test_purple_conversation_member_compare_null__not_null); g_test_add_func("/conversation-member/compare/null__null", test_purple_conversation_member_compare_null__null); g_test_add_func("/conversation-member/compare/same", test_purple_conversation_member_compare_same); g_test_add_func("/conversation-member/compare/nickname__nickname", test_purple_conversation_member_compare_nickname__nickname); g_test_add_func("/conversation-member/compare/badges__nickname", test_purple_conversation_member_compare_badges__nickname); return g_test_run(); }