Tue, 28 Jan 2025 10:56:12 -0600
Add Purple.Protocol.generate_account_name
This is the first step in allowing users to assign names to their accounts.
I also did a bunch of house keeping in the existing unit tests.
Testing Done:
Ran the tests under valgrind and called in the turtles.
Bugs closed: PIDGIN-17997
Reviewed at https://reviews.imfreedom.org/r/3787/
--- a/libpurple/purpleprotocol.c Tue Jan 28 10:53:46 2025 -0600 +++ b/libpurple/purpleprotocol.c Tue Jan 28 10:56:12 2025 -0600 @@ -163,6 +163,20 @@ NULL); } +static char * +purple_protocol_default_generate_account_name(PurpleProtocol *protocol, + G_GNUC_UNUSED PurpleAccount *account, + guint n_accounts) +{ + PurpleProtocolPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); + + priv = purple_protocol_get_instance_private(protocol); + + return g_strdup_printf("%s %u", priv->name, n_accounts + 1); +} + /****************************************************************************** * GObject Implementation *****************************************************************************/ @@ -270,6 +284,7 @@ obj_class->finalize = purple_protocol_finalize; klass->create_connection = purple_protocol_default_create_connection; + klass->generate_account_name = purple_protocol_default_generate_account_name; /** * PurpleProtocol:id: @@ -367,6 +382,24 @@ /****************************************************************************** * Public API *****************************************************************************/ +char * +purple_protocol_generate_account_name(PurpleProtocol *protocol, + PurpleAccount *account, + guint n_accounts) +{ + PurpleProtocolClass *klass = NULL; + + g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL); + g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); + + klass = PURPLE_PROTOCOL_GET_CLASS(protocol); + if(klass != NULL && klass->generate_account_name != NULL) { + return klass->generate_account_name(protocol, account, n_accounts); + } + + return NULL; +} + BirbActionMenu * purple_protocol_get_action_menu(PurpleProtocol *protocol, PurpleAccount *account)
--- a/libpurple/purpleprotocol.h Tue Jan 28 10:53:46 2025 -0600 +++ b/libpurple/purpleprotocol.h Tue Jan 28 10:56:12 2025 -0600 @@ -143,6 +143,8 @@ GList *(*get_account_options)(PurpleProtocol *protocol); PurpleWhiteboardOps *(*get_whiteboard_ops)(PurpleProtocol *protocol); + char *(*generate_account_name)(PurpleProtocol *protocol, PurpleAccount *account, guint n_accounts); + void (*can_connect_async)(PurpleProtocol *protocol, PurpleAccount *account, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); gboolean (*can_connect_finish)(PurpleProtocol *protocol, GAsyncResult *result, GError **error); @@ -175,6 +177,29 @@ G_BEGIN_DECLS /** + * purple_protocol_generate_account_name: + * @account: the account whose name to generate + * @n_accounts: the number of accounts + * + * Generates a name for an account. + * + * This is used to attempt to generate a simple name for an account. Something + * like "IRC 1". + * + * The @n_accounts parameter is the number of existing accounts with the same + * protocol. + * + * This may be called multiple times for the same account if a duplicate + * account name is found. + * + * Returns: (transfer full): The new account name. + * + * Since: 3.0 + */ +PURPLE_AVAILABLE_IN_3_0 +char *purple_protocol_generate_account_name(PurpleProtocol *protocol, PurpleAccount *account, guint n_accounts); + +/** * purple_protocol_get_id: * @protocol: The #PurpleProtocol instance. *
--- a/libpurple/tests/test_protocol.c Tue Jan 28 10:53:46 2025 -0600 +++ b/libpurple/tests/test_protocol.c Tue Jan 28 10:56:12 2025 -0600 @@ -39,8 +39,10 @@ gboolean result; GError *error; - gboolean can_connect_async; - gboolean can_connect_finish; + guint can_connect_async; + guint can_connect_finish; + + guint generate_account_name; }; G_DEFINE_FINAL_TYPE(TestPurpleProtocol, test_purple_protocol, @@ -64,7 +66,7 @@ } g_clear_object(&task); - test_protocol->can_connect_async = TRUE; + test_protocol->can_connect_async += 1; } static gboolean @@ -74,11 +76,27 @@ { TestPurpleProtocol *test_protocol = TEST_PURPLE_PROTOCOL(protocol); - test_protocol->can_connect_finish = TRUE; + test_protocol->can_connect_finish += 1; return g_task_propagate_boolean(G_TASK(result), error); } +static char * +test_purple_protocol_generate_account_name(PurpleProtocol *protocol, + PurpleAccount *account, + guint n_accounts) +{ + TestPurpleProtocol *test_protocol = NULL; + + birb_assert_type(protocol, TEST_PURPLE_TYPE_PROTOCOL); + birb_assert_type(account, PURPLE_TYPE_ACCOUNT); + + test_protocol = TEST_PURPLE_PROTOCOL(protocol); + test_protocol->generate_account_name += 1; + + return g_strdup_printf("override %u", n_accounts + 1); +} + static BirbActionMenu * test_purple_protocol_get_action_menu(PurpleProtocol *protocol, PurpleAccount *account) @@ -99,7 +117,7 @@ } static void -test_purple_protocol_init(G_GNUC_UNUSED TestPurpleProtocol *provider) { +test_purple_protocol_init(G_GNUC_UNUSED TestPurpleProtocol *protocol) { } static void @@ -112,23 +130,17 @@ protocol_class->can_connect_async = test_purple_protocol_can_connect_async; protocol_class->can_connect_finish = test_purple_protocol_can_connect_finish; + protocol_class->generate_account_name = test_purple_protocol_generate_account_name; protocol_class->get_action_menu = test_purple_protocol_get_action_menu; } -static TestPurpleProtocol * -test_purple_protocol_new(gboolean result, GError *error) { - TestPurpleProtocol *test_protocol = NULL; - - test_protocol = g_object_new( +static PurpleProtocol * +test_purple_protocol_new(void) { + return g_object_new( TEST_PURPLE_TYPE_PROTOCOL, - "id", "test-provider", - "name", "Test Provider", + "id", "test-protocol", + "name", "Test Protocol", NULL); - - test_protocol->result = result; - test_protocol->error = error; - - return test_protocol; } /****************************************************************************** @@ -157,12 +169,15 @@ static void test_purple_protocol_can_connect_error(void) { - TestPurpleProtocol *protocol = NULL; + TestPurpleProtocol *test_protocol = NULL; + PurpleProtocol *protocol = NULL; PurpleAccount *account = NULL; GError *error = NULL; error = g_error_new(TEST_PROTOCOL_DOMAIN, 0, "no network"); - protocol = test_purple_protocol_new(FALSE, error); + protocol = test_purple_protocol_new(); + test_protocol = TEST_PURPLE_PROTOCOL(protocol); + test_protocol->error = error; account = purple_account_new("test", "test"); @@ -172,8 +187,8 @@ g_main_context_iteration(NULL, FALSE); - g_assert_true(protocol->can_connect_async); - g_assert_true(protocol->can_connect_finish); + g_assert_cmpuint(test_protocol->can_connect_async, ==, 1); + g_assert_cmpuint(test_protocol->can_connect_finish, ==, 1); g_assert_finalize_object(protocol); g_clear_object(&account); @@ -181,10 +196,36 @@ static void test_purple_protocol_can_connect_false(void) { - TestPurpleProtocol *protocol = NULL; + TestPurpleProtocol *test_protocol = NULL; + PurpleProtocol *protocol = NULL; PurpleAccount *account = NULL; - protocol = test_purple_protocol_new(FALSE, NULL); + protocol = test_purple_protocol_new(); + test_protocol = TEST_PURPLE_PROTOCOL(protocol); + account = purple_account_new("test", "test"); + + purple_protocol_can_connect_async(PURPLE_PROTOCOL(protocol), account, NULL, + test_purple_protocol_can_connect_cb, + NULL); + + g_main_context_iteration(NULL, FALSE); + + g_assert_cmpuint(test_protocol->can_connect_async, ==, 1); + g_assert_cmpuint(test_protocol->can_connect_finish, ==, 1); + + g_assert_finalize_object(protocol); + g_clear_object(&account); +} + +static void +test_purple_protocol_can_connect_true(void) { + TestPurpleProtocol *test_protocol = NULL; + PurpleProtocol *protocol = NULL; + PurpleAccount *account = NULL; + + protocol = test_purple_protocol_new(); + test_protocol = TEST_PURPLE_PROTOCOL(protocol); + test_protocol->result = TRUE; account = purple_account_new("test", "test"); purple_protocol_can_connect_async(PURPLE_PROTOCOL(protocol), account, NULL, @@ -193,32 +234,66 @@ g_main_context_iteration(NULL, FALSE); - g_assert_true(protocol->can_connect_async); - g_assert_true(protocol->can_connect_finish); + g_assert_cmpuint(test_protocol->can_connect_async, ==, 1); + g_assert_cmpuint(test_protocol->can_connect_finish, ==, 1); g_assert_finalize_object(protocol); g_clear_object(&account); } static void -test_purple_protocol_can_connect_true(void) { - TestPurpleProtocol *protocol = NULL; +test_purple_protocol_generate_account_name_default(void) { + TestPurpleProtocol *test_protocol = NULL; PurpleAccount *account = NULL; + PurpleProtocol *protocol = NULL; + PurpleProtocolClass *klass = NULL; + char *name = NULL; - protocol = test_purple_protocol_new(TRUE, NULL); + protocol = test_purple_protocol_new(); + test_protocol = TEST_PURPLE_PROTOCOL(protocol); + klass = PURPLE_PROTOCOL_GET_CLASS(protocol); + klass->generate_account_name = PURPLE_PROTOCOL_CLASS(test_purple_protocol_parent_class)->generate_account_name; + account = purple_account_new("test", "test"); - purple_protocol_can_connect_async(PURPLE_PROTOCOL(protocol), account, NULL, - test_purple_protocol_can_connect_cb, - NULL); + name = purple_protocol_generate_account_name(protocol, account, 0); + g_assert_cmpstr(name, ==, "Test Protocol 1"); + g_clear_pointer(&name, g_free); - g_main_context_iteration(NULL, FALSE); + name = purple_protocol_generate_account_name(protocol, account, 9); + g_assert_cmpstr(name, ==, "Test Protocol 10"); + g_clear_pointer(&name, g_free); + + g_assert_cmpuint(test_protocol->generate_account_name, ==, 0); + + g_assert_finalize_object(account); + g_assert_finalize_object(protocol); +} - g_assert_true(protocol->can_connect_async); - g_assert_true(protocol->can_connect_finish); +static void +test_purple_protocol_generate_account_name_override(void) { + TestPurpleProtocol *test_protocol = NULL; + PurpleAccount *account = NULL; + PurpleProtocol *protocol = NULL; + char *name = NULL; + + protocol = test_purple_protocol_new(); + test_protocol = TEST_PURPLE_PROTOCOL(protocol); + + account = purple_account_new("test", "test"); + name = purple_protocol_generate_account_name(protocol, account, 0); + g_assert_cmpstr(name, ==, "override 1"); + g_clear_pointer(&name, g_free); + + name = purple_protocol_generate_account_name(protocol, account, 9); + g_assert_cmpstr(name, ==, "override 10"); + g_clear_pointer(&name, g_free); + + g_assert_cmpuint(test_protocol->generate_account_name, ==, 2); + + g_assert_finalize_object(account); g_assert_finalize_object(protocol); - g_clear_object(&account); } static void @@ -227,12 +302,7 @@ PurpleAccount *account = NULL; BirbActionMenu *action_menu = NULL; - protocol = g_object_new( - TEST_PURPLE_TYPE_PROTOCOL, - "id", "test-provider", - "name", "Test Provider", - NULL); - + protocol = test_purple_protocol_new(); account = purple_account_new("test", "test"); action_menu = purple_protocol_get_action_menu(protocol, account); @@ -257,6 +327,12 @@ test_purple_protocol_can_connect_false); g_test_add_func("/protocol/can-connect/true", test_purple_protocol_can_connect_true); + + g_test_add_func("/protocol/generate-account-name/override", + test_purple_protocol_generate_account_name_override); + g_test_add_func("/protocol/generate-account-name/default", + test_purple_protocol_generate_account_name_default); + g_test_add_func("/protocol/get-action-menu/valid", test_purple_protocol_get_action_menu_valid);