libgnunetchat

library for GNUnet Messenger
Log | Files | Refs | README | LICENSE

commit 07dfa4175378db8b25d9d9024b5bf4391bf45561
parent 296e5f5846c60f1419309f452fdac2cad2a8b133
Author: Jacki <jacki@thejackimonster.de>
Date:   Sun,  6 Oct 2024 15:45:27 +0200

Implement test cases for tagging and fix hashing tags

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Msrc/gnunet_chat_contact_intern.c | 2+-
Msrc/internal/gnunet_chat_tagging.c | 32+++++++++++++++++---------------
Mtests/meson.build | 4++++
Atests/tag/meson.build | 37+++++++++++++++++++++++++++++++++++++
Atests/tag/test_gnunet_chat_tag_contact.c | 197+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/tag/test_gnunet_chat_tag_message.c | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 460 insertions(+), 16 deletions(-)

diff --git a/src/gnunet_chat_contact_intern.c b/src/gnunet_chat_contact_intern.c @@ -102,7 +102,7 @@ it_contact_iterate_unique_tag (void *cls, struct GNUNET_CHAT_ContactIterateUniqueTag *it = cls; struct GNUNET_HashCode hash; - GNUNET_CRYPTO_hash_from_string(tag, &hash); + GNUNET_CRYPTO_hash(tag, strlen(tag), &hash); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(it->tags, &hash)) return GNUNET_YES; diff --git a/src/internal/gnunet_chat_tagging.c b/src/internal/gnunet_chat_tagging.c @@ -27,6 +27,7 @@ #include <gnunet/gnunet_common.h> #include <gnunet/gnunet_messenger_service.h> +#include <gnunet/gnunet_util_lib.h> #include <string.h> static const unsigned int initial_map_size_of_tagging = 4; @@ -55,6 +56,17 @@ internal_tagging_destroy (struct GNUNET_CHAT_InternalTagging *tagging) GNUNET_free(tagging); } +static void +convert_tag_to_hash (const char *tag, struct GNUNET_HashCode *hash) +{ + GNUNET_assert(hash); + + if (tag) + GNUNET_CRYPTO_hash(tag, strlen(tag), hash); + else + memset(hash, 0, sizeof(*hash)); +} + enum GNUNET_GenericReturnValue internal_tagging_add (struct GNUNET_CHAT_InternalTagging *tagging, struct GNUNET_CHAT_Message *message) @@ -66,12 +78,9 @@ internal_tagging_add (struct GNUNET_CHAT_InternalTagging *tagging, return GNUNET_SYSERR; const char *tag = message->msg->body.tag.tag; + struct GNUNET_HashCode hash; - - if (tag) - GNUNET_CRYPTO_hash_from_string(tag, &hash); - else - memset(&hash, 0, sizeof(hash)); + convert_tag_to_hash(tag, &hash); return GNUNET_CONTAINER_multihashmap_put( tagging->tags, @@ -92,12 +101,9 @@ internal_tagging_remove (struct GNUNET_CHAT_InternalTagging *tagging, return GNUNET_SYSERR; const char *tag = message->msg->body.tag.tag; + struct GNUNET_HashCode hash; - - if (tag) - GNUNET_CRYPTO_hash_from_string(tag, &hash); - else - memset(&hash, 0, sizeof(hash)); + convert_tag_to_hash(tag, &hash); return GNUNET_CONTAINER_multihashmap_remove( tagging->tags, @@ -147,11 +153,7 @@ internal_tagging_iterate (const struct GNUNET_CHAT_InternalTagging *tagging, ); struct GNUNET_HashCode hash; - - if (tag) - GNUNET_CRYPTO_hash_from_string(tag, &hash); - else - memset(&hash, 0, sizeof(hash)); + convert_tag_to_hash(tag, &hash); return GNUNET_CONTAINER_multihashmap_get_multiple( tagging->tags, diff --git a/tests/meson.build b/tests/meson.build @@ -32,6 +32,7 @@ subdir('group') subdir('handle') subdir('lobby') subdir('message') +subdir('tag') test('test_gnunet_chat_handle_init', test_gnunet_chat_handle_init, depends: gnunetchat_lib, is_parallel : false) test('test_gnunet_chat_handle_accounts', test_gnunet_chat_handle_accounts, depends: gnunetchat_lib, is_parallel : false) @@ -53,3 +54,6 @@ test('test_gnunet_chat_attribute_share', test_gnunet_chat_attribute_share, depen test('test_gnunet_chat_discourse_open', test_gnunet_chat_discourse_open, depends: gnunetchat_lib, is_parallel : false) test('test_gnunet_chat_discourse_write', test_gnunet_chat_discourse_write, depends: gnunetchat_lib, is_parallel : false) + +test('test_gnunet_chat_tag_contact', test_gnunet_chat_tag_contact, depends: gnunetchat_lib, is_parallel : false) +test('test_gnunet_chat_tag_message', test_gnunet_chat_tag_message, depends: gnunetchat_lib, is_parallel : false) diff --git a/tests/tag/meson.build b/tests/tag/meson.build @@ -0,0 +1,37 @@ +# +# This file is part of GNUnet. +# Copyright (C) 2024 GNUnet e.V. +# +# GNUnet is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, +# or (at your option) any later version. +# +# GNUnet 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# SPDX-License-Identifier: AGPL3.0-or-later +# + +test_gnunet_chat_tag_contact = executable( + 'test_gnunet_chat_tag_contact.test', + 'test_gnunet_chat_tag_contact.c', + dependencies: test_deps, + link_with: gnunetchat_lib, + include_directories: tests_include, + extra_files: test_header, +) + +test_gnunet_chat_tag_message = executable( + 'test_gnunet_chat_tag_message.test', + 'test_gnunet_chat_tag_message.c', + dependencies: test_deps, + link_with: gnunetchat_lib, + include_directories: tests_include, + extra_files: test_header, +) diff --git a/tests/tag/test_gnunet_chat_tag_contact.c b/tests/tag/test_gnunet_chat_tag_contact.c @@ -0,0 +1,197 @@ +/* + This file is part of GNUnet. + Copyright (C) 2024 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/* + * @author Tobias Frisch + * @file test_gnunet_chat_tag_contact.c + */ + +#include "test_gnunet_chat.h" + +#define TEST_TAG_ID "gnunet_chat_tag_contact" +#define TEST_TAG_GROUP "gnunet_chat_tag_contact_group" +#define TEST_TAG_CONTACT_TAG "test_contact_tag_tagged" + +enum GNUNET_GenericReturnValue +on_gnunet_chat_tag_contact_msg(void *cls, + struct GNUNET_CHAT_Context *context, + struct GNUNET_CHAT_Message *message) +{ + static unsigned int tag_stage = 0; + + struct GNUNET_CHAT_Handle *handle = *( + (struct GNUNET_CHAT_Handle**) cls + ); + + struct GNUNET_CHAT_Account *account; + struct GNUNET_CHAT_Group *group; + struct GNUNET_CHAT_Contact *contact; + const char *text; + + ck_assert_ptr_nonnull(handle); + ck_assert_ptr_nonnull(message); + + account = GNUNET_CHAT_message_get_account(message); + contact = GNUNET_CHAT_message_get_sender(message); + + switch (GNUNET_CHAT_message_get_kind(message)) + { + case GNUNET_CHAT_KIND_WARNING: + ck_abort_msg("%s\n", GNUNET_CHAT_message_get_text(message)); + break; + case GNUNET_CHAT_KIND_REFRESH: + ck_assert_ptr_null(context); + ck_assert_ptr_null(account); + + if (tag_stage == 0) + { + account = GNUNET_CHAT_find_account(handle, TEST_TAG_ID); + + ck_assert_ptr_nonnull(account); + + GNUNET_CHAT_connect(handle, account); + tag_stage = 1; + } + + break; + case GNUNET_CHAT_KIND_LOGIN: + ck_assert_ptr_null(context); + ck_assert_ptr_nonnull(account); + ck_assert_uint_eq(tag_stage, 1); + + group = GNUNET_CHAT_group_create(handle, TEST_TAG_GROUP); + + ck_assert_ptr_nonnull(group); + + tag_stage = 2; + break; + case GNUNET_CHAT_KIND_LOGOUT: + ck_assert_ptr_null(context); + ck_assert_ptr_nonnull(account); + ck_assert_uint_eq(tag_stage, 6); + + GNUNET_CHAT_stop(handle); + break; + case GNUNET_CHAT_KIND_UPDATE_ACCOUNT: + ck_assert_ptr_nonnull(account); + break; + case GNUNET_CHAT_KIND_UPDATE_CONTEXT: + ck_assert_ptr_nonnull(context); + break; + case GNUNET_CHAT_KIND_JOIN: + ck_assert_ptr_nonnull(context); + ck_assert_ptr_nonnull(contact); + ck_assert_uint_eq(tag_stage, 2); + + ck_assert_int_eq(GNUNET_CHAT_contact_is_tagged( + contact, TEST_TAG_CONTACT_TAG + ), GNUNET_NO); + + GNUNET_CHAT_contact_tag( + contact, + TEST_TAG_CONTACT_TAG + ); + + tag_stage = 3; + break; + case GNUNET_CHAT_KIND_LEAVE: + ck_assert_ptr_nonnull(context); + ck_assert_uint_eq(tag_stage, 5); + + GNUNET_CHAT_disconnect(handle); + + tag_stage = 6; + break; + case GNUNET_CHAT_KIND_CONTACT: + ck_assert_ptr_nonnull(context); + ck_assert_ptr_nonnull(contact); + break; + case GNUNET_CHAT_KIND_TAG: + ck_assert_ptr_nonnull(context); + ck_assert_uint_ge(tag_stage, 3); + + if (GNUNET_YES == GNUNET_CHAT_message_is_deleted(message)) + break; + + ck_assert_uint_eq(tag_stage, 3); + + text = GNUNET_CHAT_message_get_text(message); + + ck_assert_str_eq(text, TEST_TAG_CONTACT_TAG); + + message = GNUNET_CHAT_message_get_target(message); + + ck_assert_ptr_nonnull(message); + + contact = GNUNET_CHAT_message_get_sender(message); + + ck_assert_ptr_nonnull(contact); + + ck_assert_int_eq(GNUNET_CHAT_contact_is_tagged( + contact, TEST_TAG_CONTACT_TAG + ), GNUNET_YES); + + GNUNET_CHAT_contact_untag( + contact, + TEST_TAG_CONTACT_TAG + ); + + tag_stage = 4; + break; + case GNUNET_CHAT_KIND_DELETION: + ck_assert_ptr_nonnull(context); + ck_assert_uint_eq(tag_stage, 4); + + group = GNUNET_CHAT_context_get_group(context); + + ck_assert_ptr_nonnull(group); + + ck_assert_int_eq( + GNUNET_CHAT_group_leave(group), + GNUNET_OK + ); + + tag_stage = 5; + break; + default: + ck_abort_msg("%d\n", GNUNET_CHAT_message_get_kind(message)); + break; + } + + return GNUNET_YES; +} + +REQUIRE_GNUNET_CHAT_ACCOUNT(gnunet_chat_tag_contact, TEST_TAG_ID) + +void +call_gnunet_chat_tag_contact(const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + static struct GNUNET_CHAT_Handle *handle = NULL; + handle = GNUNET_CHAT_start(cfg, on_gnunet_chat_tag_contact_msg, &handle); + + ck_assert_ptr_nonnull(handle); +} + +CREATE_GNUNET_TEST(test_gnunet_chat_tag_contact, gnunet_chat_tag_contact) + +START_SUITE(handle_suite, "Tag") +ADD_TEST_TO_SUITE(test_gnunet_chat_tag_contact, "Contact") +END_SUITE + +MAIN_SUITE(handle_suite, CK_NORMAL) diff --git a/tests/tag/test_gnunet_chat_tag_message.c b/tests/tag/test_gnunet_chat_tag_message.c @@ -0,0 +1,204 @@ +/* + This file is part of GNUnet. + Copyright (C) 2024 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/* + * @author Tobias Frisch + * @file test_gnunet_chat_tag_message.c + */ + +#include "test_gnunet_chat.h" +#include <gnunet/gnunet_time_lib.h> + +#define TEST_TAG_ID "gnunet_chat_tag_message" +#define TEST_TAG_GROUP "gnunet_chat_tag_message_group" +#define TEST_TAG_MSG "test_message_tag" +#define TEST_TAG_MSG_TAG "test_message_tag_tagged" + +enum GNUNET_GenericReturnValue +on_gnunet_chat_tag_message_msg(void *cls, + struct GNUNET_CHAT_Context *context, + struct GNUNET_CHAT_Message *message) +{ + static unsigned int tag_stage = 0; + + struct GNUNET_CHAT_Handle *handle = *( + (struct GNUNET_CHAT_Handle**) cls + ); + + struct GNUNET_CHAT_Account *account; + struct GNUNET_CHAT_Group *group; + const char *text; + + ck_assert_ptr_nonnull(handle); + ck_assert_ptr_nonnull(message); + + account = GNUNET_CHAT_message_get_account(message); + + switch (GNUNET_CHAT_message_get_kind(message)) + { + case GNUNET_CHAT_KIND_WARNING: + ck_abort_msg("%s\n", GNUNET_CHAT_message_get_text(message)); + break; + case GNUNET_CHAT_KIND_REFRESH: + ck_assert_ptr_null(context); + ck_assert_ptr_null(account); + + if (tag_stage == 0) + { + account = GNUNET_CHAT_find_account(handle, TEST_TAG_ID); + + ck_assert_ptr_nonnull(account); + + GNUNET_CHAT_connect(handle, account); + tag_stage = 1; + } + + break; + case GNUNET_CHAT_KIND_LOGIN: + ck_assert_ptr_null(context); + ck_assert_ptr_nonnull(account); + ck_assert_uint_eq(tag_stage, 1); + + group = GNUNET_CHAT_group_create(handle, TEST_TAG_GROUP); + + ck_assert_ptr_nonnull(group); + + tag_stage = 2; + break; + case GNUNET_CHAT_KIND_LOGOUT: + ck_assert_ptr_null(context); + ck_assert_ptr_nonnull(account); + ck_assert_uint_eq(tag_stage, 7); + + GNUNET_CHAT_stop(handle); + break; + case GNUNET_CHAT_KIND_UPDATE_ACCOUNT: + ck_assert_ptr_nonnull(account); + break; + case GNUNET_CHAT_KIND_UPDATE_CONTEXT: + ck_assert_ptr_nonnull(context); + break; + case GNUNET_CHAT_KIND_JOIN: + ck_assert_ptr_nonnull(context); + ck_assert_uint_eq(tag_stage, 2); + + ck_assert_int_eq(GNUNET_CHAT_context_send_text( + context, TEST_TAG_MSG + ), GNUNET_OK); + + tag_stage = 3; + break; + case GNUNET_CHAT_KIND_LEAVE: + ck_assert_ptr_nonnull(context); + ck_assert_uint_eq(tag_stage, 6); + + GNUNET_CHAT_disconnect(handle); + tag_stage = 7; + break; + case GNUNET_CHAT_KIND_CONTACT: + ck_assert_ptr_nonnull(context); + break; + case GNUNET_CHAT_KIND_TEXT: + ck_assert_ptr_nonnull(context); + ck_assert_uint_eq(tag_stage, 3); + + group = GNUNET_CHAT_context_get_group(context); + + ck_assert_ptr_nonnull(group); + + text = GNUNET_CHAT_message_get_text(message); + + ck_assert_str_eq(text, TEST_TAG_MSG); + ck_assert_int_eq(GNUNET_CHAT_message_is_tagged( + message, TEST_TAG_MSG_TAG + ), GNUNET_NO); + + ck_assert_int_eq(GNUNET_CHAT_context_send_tag( + context, message, TEST_TAG_MSG_TAG + ), GNUNET_OK); + + tag_stage = 4; + break; + case GNUNET_CHAT_KIND_TAG: + ck_assert_ptr_nonnull(context); + ck_assert_uint_ge(tag_stage, 4); + + if (GNUNET_YES == GNUNET_CHAT_message_is_deleted(message)) + break; + + ck_assert_uint_eq(tag_stage, 4); + + text = GNUNET_CHAT_message_get_text(message); + + ck_assert_str_eq(text, TEST_TAG_MSG_TAG); + ck_assert_int_eq(GNUNET_CHAT_message_delete( + message, 0 + ), GNUNET_OK); + + message = GNUNET_CHAT_message_get_target(message); + + ck_assert_ptr_nonnull(message); + + text = GNUNET_CHAT_message_get_text(message); + + ck_assert_str_eq(text, TEST_TAG_MSG); + + tag_stage = 5; + break; + case GNUNET_CHAT_KIND_DELETION: + ck_assert_ptr_nonnull(context); + ck_assert_uint_eq(tag_stage, 5); + + group = GNUNET_CHAT_context_get_group(context); + + ck_assert_ptr_nonnull(group); + + ck_assert_int_eq( + GNUNET_CHAT_group_leave(group), + GNUNET_OK + ); + + tag_stage = 6; + break; + default: + ck_abort_msg("%d\n", GNUNET_CHAT_message_get_kind(message)); + break; + } + + return GNUNET_YES; +} + +REQUIRE_GNUNET_CHAT_ACCOUNT(gnunet_chat_tag_message, TEST_TAG_ID) + +void +call_gnunet_chat_tag_message(const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + static struct GNUNET_CHAT_Handle *handle = NULL; + handle = GNUNET_CHAT_start(cfg, on_gnunet_chat_tag_message_msg, &handle); + + ck_assert_ptr_nonnull(handle); +} + +CREATE_GNUNET_TEST(test_gnunet_chat_tag_message, gnunet_chat_tag_message) + +START_SUITE(handle_suite, "Tag") +ADD_TEST_TO_SUITE(test_gnunet_chat_tag_message, "Message") +END_SUITE + +MAIN_SUITE(handle_suite, CK_NORMAL)