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:
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)