pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Fix leaks from g_list_model_get_item
14 months ago, Elliott Sales de Andrade
b8bb444799a4
Fix leaks from g_list_model_get_item
It returns a new reference, which needs to be unref'd.
Testing Done:
Compiled only, and ran tests, though these issues didn't show up in valgrind anyway.
Reviewed at https://reviews.imfreedom.org/r/2377/
/*
* 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>
#include
"test_ui.h"
/******************************************************************************
* Callbacks
*****************************************************************************/
static
void
test_purple_person_items_changed_cb
(
G_GNUC_UNUSED
GListModel
*
model
,
G_GNUC_UNUSED
guint
position
,
G_GNUC_UNUSED
guint
removed
,
G_GNUC_UNUSED
guint
added
,
gpointer
data
)
{
gboolean
*
called
=
data
;
*
called
=
TRUE
;
}
static
void
test_purple_person_notify_cb
(
G_GNUC_UNUSED
GObject
*
obj
,
G_GNUC_UNUSED
GParamSpec
*
pspec
,
gpointer
data
)
{
gboolean
*
called
=
data
;
*
called
=
TRUE
;
}
/******************************************************************************
* Tests
*****************************************************************************/
static
void
test_purple_person_new
(
void
)
{
PurplePerson
*
person
=
NULL
;
person
=
purple_person_new
();
g_assert_true
(
PURPLE_IS_PERSON
(
person
));
g_clear_object
(
&
person
);
}
static
void
test_purple_person_properties
(
void
)
{
PurpleContact
*
person
=
NULL
;
PurpleTags
*
tags
=
NULL
;
GdkPixbuf
*
avatar
=
NULL
;
GdkPixbuf
*
avatar1
=
NULL
;
GdkPixbuf
*
avatar_for_display
=
NULL
;
char
*
id
=
NULL
;
char
*
alias
=
NULL
;
char
*
name_for_display
=
NULL
;
/* Create our avatar for testing. */
avatar
=
gdk_pixbuf_new
(
GDK_COLORSPACE_RGB
,
FALSE
,
8
,
1
,
1
);
/* 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.
*/
person
=
g_object_new
(
PURPLE_TYPE_PERSON
,
"alias"
,
"alias"
,
"avatar"
,
avatar
,
NULL
);
/* Now use g_object_get to read all of the properties. */
g_object_get
(
person
,
"id"
,
&
id
,
"alias"
,
&
alias
,
"avatar"
,
&
avatar1
,
"avatar-for-display"
,
&
avatar_for_display
,
"name-for-display"
,
&
name_for_display
,
"tags"
,
&
tags
,
NULL
);
/* Compare all the things. */
g_assert_nonnull
(
id
);
g_assert_cmpstr
(
alias
,
==
,
"alias"
);
g_assert_true
(
avatar1
==
avatar
);
g_assert_true
(
avatar1
==
avatar_for_display
);
g_assert_cmpstr
(
name_for_display
,
==
,
"alias"
);
g_assert_nonnull
(
tags
);
/* Free/unref all the things. */
g_clear_pointer
(
&
id
,
g_free
);
g_clear_pointer
(
&
alias
,
g_free
);
g_clear_object
(
&
avatar1
);
g_clear_object
(
&
avatar_for_display
);
g_clear_pointer
(
&
name_for_display
,
g_free
);
g_clear_object
(
&
tags
);
g_clear_object
(
&
avatar
);
g_clear_object
(
&
person
);
}
static
void
test_purple_person_avatar_for_display_person
(
void
)
{
PurpleContactInfo
*
info
=
NULL
;
PurplePerson
*
person
=
NULL
;
GdkPixbuf
*
avatar
=
NULL
;
person
=
purple_person_new
();
avatar
=
gdk_pixbuf_new
(
GDK_COLORSPACE_RGB
,
FALSE
,
8
,
1
,
1
);
purple_person_set_avatar
(
person
,
avatar
);
info
=
purple_contact_info_new
(
"id"
);
purple_person_add_contact_info
(
person
,
info
);
/* Make sure the person's alias is overriding the contact info. */
g_assert_true
(
purple_person_get_avatar_for_display
(
person
)
==
avatar
);
g_clear_object
(
&
info
);
g_clear_object
(
&
person
);
g_clear_object
(
&
avatar
);
}
static
void
test_purple_person_avatar_for_display_contact
(
void
)
{
PurpleContactInfo
*
info
=
NULL
;
PurplePerson
*
person
=
NULL
;
GdkPixbuf
*
avatar
=
NULL
;
person
=
purple_person_new
();
info
=
purple_contact_info_new
(
"id"
);
avatar
=
gdk_pixbuf_new
(
GDK_COLORSPACE_RGB
,
FALSE
,
8
,
1
,
1
);
purple_contact_info_set_avatar
(
info
,
avatar
);
purple_person_add_contact_info
(
person
,
info
);
/* Make sure the person's alias is overriding the contact info. */
g_assert_true
(
purple_person_get_avatar_for_display
(
person
)
==
avatar
);
g_clear_object
(
&
info
);
g_clear_object
(
&
person
);
g_clear_object
(
&
avatar
);
}
static
void
test_purple_person_name_for_display_person
(
void
)
{
PurpleContactInfo
*
info
=
NULL
;
PurplePerson
*
person
=
NULL
;
person
=
purple_person_new
();
purple_person_set_alias
(
person
,
"person-alias"
);
info
=
purple_contact_info_new
(
"id"
);
purple_person_add_contact_info
(
person
,
info
);
/* Make sure the person's alias is overriding the contact info. */
g_assert_cmpstr
(
purple_person_get_name_for_display
(
person
),
==
,
"person-alias"
);
g_clear_object
(
&
info
);
g_clear_object
(
&
person
);
}
static
void
test_purple_person_name_for_display_contact
(
void
)
{
PurpleContactInfo
*
info
=
NULL
;
PurplePerson
*
person
=
NULL
;
person
=
purple_person_new
();
info
=
purple_contact_info_new
(
"id"
);
purple_person_add_contact_info
(
person
,
info
);
/* Make sure the contact info's name for display is called when the
* person's alias is unset.
*/
g_assert_cmpstr
(
purple_person_get_name_for_display
(
person
),
==
,
"id"
);
g_clear_object
(
&
info
);
g_clear_object
(
&
person
);
}
static
void
test_purple_person_contacts_single
(
void
)
{
PurpleContactInfo
*
info
=
NULL
;
PurplePerson
*
person
=
NULL
;
PurplePerson
*
person1
=
NULL
;
guint
n_items
=
0
;
gboolean
removed
=
FALSE
;
gboolean
changed
=
FALSE
;
info
=
purple_contact_info_new
(
"id"
);
person
=
purple_person_new
();
g_signal_connect
(
person
,
"items-changed"
,
G_CALLBACK
(
test_purple_person_items_changed_cb
),
&
changed
);
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
0
);
purple_person_add_contact_info
(
person
,
info
);
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
1
);
g_assert_true
(
changed
);
person1
=
purple_contact_info_get_person
(
info
);
g_assert_true
(
person1
==
person
);
changed
=
FALSE
;
removed
=
purple_person_remove_contact_info
(
person
,
info
);
g_assert_true
(
removed
);
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
0
);
g_assert_true
(
changed
);
person1
=
purple_contact_info_get_person
(
info
);
g_assert_null
(
person1
);
g_clear_object
(
&
person
);
g_clear_object
(
&
info
);
}
static
void
test_purple_person_contacts_multiple
(
void
)
{
PurplePerson
*
person
=
NULL
;
GPtrArray
*
infos
=
NULL
;
guint
n_items
=
0
;
const
gint
n_infos
=
5
;
gboolean
changed
=
FALSE
;
person
=
purple_person_new
();
g_signal_connect
(
person
,
"items-changed"
,
G_CALLBACK
(
test_purple_person_items_changed_cb
),
&
changed
);
infos
=
g_ptr_array_new_full
(
n_infos
,
g_object_unref
);
for
(
gint
i
=
0
;
i
<
n_infos
;
i
++
)
{
PurpleContactInfo
*
info
=
NULL
;
gchar
*
username
=
NULL
;
changed
=
FALSE
;
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
i
);
username
=
g_strdup_printf
(
"username%d"
,
i
);
info
=
purple_contact_info_new
(
NULL
);
purple_contact_info_set_username
(
info
,
username
);
g_free
(
username
);
/* Add the contact info to the ptr array so we can remove it below. */
g_ptr_array_add
(
infos
,
info
);
/* Add the contact info to the person and make sure that all the magic
* happened.
*/
purple_person_add_contact_info
(
person
,
info
);
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
i
+
1
);
g_assert_true
(
changed
);
}
for
(
gint
i
=
0
;
i
<
n_infos
;
i
++
)
{
PurpleContactInfo
*
info
=
g_ptr_array_index
(
infos
,
i
);
gboolean
removed
=
FALSE
;
changed
=
FALSE
;
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
n_infos
-
i
);
removed
=
purple_person_remove_contact_info
(
person
,
info
);
g_assert_true
(
removed
);
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
n_infos
-
(
i
+
1
));
g_assert_true
(
changed
);
}
/* Final sanity check that the person has no more contacts. */
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
0
);
g_ptr_array_free
(
infos
,
TRUE
);
g_clear_object
(
&
person
);
}
static
void
test_purple_person_priority_single
(
void
)
{
PurpleContactInfo
*
info
=
NULL
;
PurpleContactInfo
*
priority
=
NULL
;
PurplePerson
*
person
=
NULL
;
PurplePresence
*
presence
=
NULL
;
PurpleStatus
*
status
=
NULL
;
PurpleStatusType
*
status_type
=
NULL
;
gboolean
called
=
FALSE
;
person
=
purple_person_new
();
g_signal_connect
(
person
,
"notify::priority-contact-info"
,
G_CALLBACK
(
test_purple_person_notify_cb
),
&
called
);
priority
=
purple_person_get_priority_contact_info
(
person
);
g_assert_null
(
priority
);
/* Now create a real contact. */
info
=
purple_contact_info_new
(
NULL
);
purple_person_add_contact_info
(
person
,
info
);
/* Set the status of the contact. */
presence
=
purple_contact_info_get_presence
(
info
);
status_type
=
purple_status_type_new
(
PURPLE_STATUS_AVAILABLE
,
"available"
,
"Available"
,
FALSE
);
status
=
purple_status_new
(
status_type
,
presence
);
g_object_set
(
G_OBJECT
(
presence
),
"active-status"
,
status
,
NULL
);
g_clear_object
(
&
status
);
g_assert_true
(
called
);
priority
=
purple_person_get_priority_contact_info
(
person
);
g_assert_true
(
priority
==
info
);
purple_status_type_destroy
(
status_type
);
g_clear_object
(
&
person
);
g_clear_object
(
&
info
);
g_clear_object
(
&
presence
);
}
static
void
test_purple_person_priority_multiple_with_change
(
void
)
{
PurpleContactInfo
*
priority
=
NULL
;
PurpleContactInfo
*
first
=
NULL
;
PurpleContactInfo
*
sorted_contact
=
NULL
;
PurplePerson
*
person
=
NULL
;
PurplePresence
*
sorted_presence
=
NULL
;
PurpleStatus
*
status
=
NULL
;
PurpleStatusType
*
available
=
NULL
;
PurpleStatusType
*
offline
=
NULL
;
gboolean
changed
=
FALSE
;
gint
n_infos
=
5
;
guint
n_items
=
0
;
/* This unit test is a bit complicated, but it adds 5 contact infos to a
* person all whose presences are set to offline. After adding all the
* contact infos, we verify that the first contact info we added is the
* priority contact info. Then we flip the active status of the n_infos - 2
* infos to available. This should make it the priority contact info which
* we then assert.
*/
/* Create our status types. */
available
=
purple_status_type_new
(
PURPLE_STATUS_AVAILABLE
,
"available"
,
"Available"
,
FALSE
);
offline
=
purple_status_type_new
(
PURPLE_STATUS_OFFLINE
,
"offline"
,
"Offline"
,
FALSE
);
/* Create the person and connected to the notify signal for the
* priority-contact property.
*/
person
=
purple_person_new
();
g_signal_connect
(
person
,
"notify::priority-contact-info"
,
G_CALLBACK
(
test_purple_person_notify_cb
),
&
changed
);
priority
=
purple_person_get_priority_contact_info
(
person
);
g_assert_null
(
priority
);
/* Create and add all contact infos. */
for
(
gint
i
=
0
;
i
<
n_infos
;
i
++
)
{
PurpleContactInfo
*
info
=
NULL
;
PurplePresence
*
presence
=
NULL
;
gchar
*
username
=
NULL
;
/* Set changed to false as it shouldn't be changed. */
changed
=
FALSE
;
/* Now create a real contact. */
username
=
g_strdup_printf
(
"username%d"
,
i
+
1
);
info
=
purple_contact_info_new
(
NULL
);
purple_contact_info_set_username
(
info
,
username
);
g_free
(
username
);
/* Set the status for the contact. */
presence
=
purple_contact_info_get_presence
(
info
);
status
=
purple_status_new
(
offline
,
presence
);
g_object_set
(
G_OBJECT
(
presence
),
"active-status"
,
status
,
NULL
);
g_clear_object
(
&
status
);
purple_person_add_contact_info
(
person
,
info
);
if
(
i
==
0
)
{
first
=
g_object_ref
(
info
);
g_assert_true
(
changed
);
}
else
{
g_assert_false
(
changed
);
if
(
i
==
n_infos
-
2
)
{
sorted_contact
=
g_object_ref
(
info
);
sorted_presence
=
g_object_ref
(
presence
);
}
}
g_clear_object
(
&
info
);
}
n_items
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
person
));
g_assert_cmpuint
(
n_items
,
==
,
n_infos
);
priority
=
purple_person_get_priority_contact_info
(
person
);
g_assert_true
(
priority
==
first
);
g_clear_object
(
&
first
);
/* Now set the second from the last contact info's status to available, and
* verify that that contact info is now the priority contact info.
*/
changed
=
FALSE
;
status
=
purple_status_new
(
available
,
sorted_presence
);
g_object_set
(
G_OBJECT
(
sorted_presence
),
"active-status"
,
status
,
NULL
);
g_clear_object
(
&
status
);
g_assert_true
(
changed
);
priority
=
purple_person_get_priority_contact_info
(
person
);
g_assert_true
(
priority
==
sorted_contact
);
/* Cleanup. */
purple_status_type_destroy
(
offline
);
purple_status_type_destroy
(
available
);
g_clear_object
(
&
sorted_contact
);
g_clear_object
(
&
sorted_presence
);
g_clear_object
(
&
person
);
}
/******************************************************************************
* Matches tests
*****************************************************************************/
static
void
test_purple_person_matches_accepts_null
(
void
)
{
PurplePerson
*
person
=
purple_person_new
();
g_assert_true
(
purple_person_matches
(
person
,
NULL
));
g_clear_object
(
&
person
);
}
static
void
test_purple_person_matches_empty_string
(
void
)
{
PurplePerson
*
person
=
purple_person_new
();
g_assert_true
(
purple_person_matches
(
person
,
""
));
g_clear_object
(
&
person
);
}
static
void
test_purple_person_matches_alias
(
void
)
{
PurplePerson
*
person
=
purple_person_new
();
purple_person_set_alias
(
person
,
"this is the alias"
);
g_assert_true
(
purple_person_matches
(
person
,
"the"
));
g_assert_false
(
purple_person_matches
(
person
,
"what"
));
g_clear_object
(
&
person
);
}
static
void
test_purple_person_matches_contact_info
(
void
)
{
PurplePerson
*
person
=
purple_person_new
();
PurpleContactInfo
*
info
=
purple_contact_info_new
(
NULL
);
purple_contact_info_set_username
(
info
,
"user1"
);
purple_person_add_contact_info
(
person
,
info
);
g_clear_object
(
&
info
);
g_assert_true
(
purple_person_matches
(
person
,
"user1"
));
g_clear_object
(
&
person
);
}
/******************************************************************************
* Main
*****************************************************************************/
gint
main
(
gint
argc
,
gchar
*
argv
[])
{
g_test_init
(
&
argc
,
&
argv
,
NULL
);
test_ui_purple_init
();
g_test_add_func
(
"/person/new"
,
test_purple_person_new
);
g_test_add_func
(
"/person/properties"
,
test_purple_person_properties
);
g_test_add_func
(
"/person/avatar-for-display/person"
,
test_purple_person_avatar_for_display_person
);
g_test_add_func
(
"/person/avatar-for-display/contact"
,
test_purple_person_avatar_for_display_contact
);
g_test_add_func
(
"/person/name-for-display/person"
,
test_purple_person_name_for_display_person
);
g_test_add_func
(
"/person/name-for-display/contact"
,
test_purple_person_name_for_display_contact
);
g_test_add_func
(
"/person/contacts/single"
,
test_purple_person_contacts_single
);
g_test_add_func
(
"/person/contacts/multiple"
,
test_purple_person_contacts_multiple
);
g_test_add_func
(
"/person/priority/single"
,
test_purple_person_priority_single
);
g_test_add_func
(
"/person/priority/multiple-with-change"
,
test_purple_person_priority_multiple_with_change
);
g_test_add_func
(
"/person/matches/accepts_null"
,
test_purple_person_matches_accepts_null
);
g_test_add_func
(
"/person/matches/empty_string"
,
test_purple_person_matches_empty_string
);
g_test_add_func
(
"/person/matches/alias"
,
test_purple_person_matches_alias
);
g_test_add_func
(
"/person/matches/contact_info"
,
test_purple_person_matches_contact_info
);
return
g_test_run
();
}