summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/.gitignore2
-rw-r--r--lib/CMakeLists.txt88
-rw-r--r--lib/src/turns-disposition.h18
-rw-r--r--lib/src/turns-enums.c.in37
-rw-r--r--lib/src/turns-enums.h.in25
-rw-r--r--lib/src/turns-init.cpp17
-rw-r--r--lib/src/turns-init.h12
-rw-r--r--lib/src/turns-participant.cpp202
-rw-r--r--lib/src/turns-participant.h84
-rw-r--r--lib/tests/runtime_init.cpp21
-rw-r--r--lib/tests/turns-participant.cpp353
11 files changed, 859 insertions, 0 deletions
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..0050be3
--- /dev/null
+++ b/lib/.gitignore
@@ -0,0 +1,2 @@
+turns-enums.c
+turns-enums.h \ No newline at end of file
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644
index 0000000..8e507ec
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,88 @@
+# Library
+
+set(HEADERS
+ "src/turns-disposition.h"
+ "src/turns-init.h"
+ "src/turns-participant.h"
+)
+
+set(SOURCES
+ "src/turns-init.cpp"
+ "src/turns-participant.cpp"
+)
+
+add_library("lib"
+ ${SOURCES}
+)
+
+add_library("turns::lib" ALIAS "lib")
+
+target_sources("lib" PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS "src"
+ FILES
+ ${HEADERS}
+)
+
+target_compile_options("lib" PUBLIC
+ "$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall>"
+ "$<$<CXX_COMPILER_ID:GNU,Clang>:-Wextra>"
+ "$<$<CXX_COMPILER_ID:GNU,Clang>:-Werror>"
+ "$<$<CXX_COMPILER_ID:GNU,Clang>:-pedantic-errors>"
+)
+
+target_include_directories("lib" PUBLIC
+ "src"
+)
+
+target_link_libraries("lib" PUBLIC
+ "PkgConfig::gobject"
+)
+
+target_compile_definitions("lib" PUBLIC
+ "$<$<NOT:$<BOOL:TURNS_USE_INSTALLED_SCHEMA_FILES>>:TURNS_SETTINGS_SCHEMA_DIR=\"${CMAKE_CURRENT_BINARY_DIR}\">"
+)
+
+set_target_properties("lib" PROPERTIES
+ OUTPUT_NAME "turns"
+)
+
+target_add_glib_enums("lib"
+ HEADER_TEMPLATE "src/turns-enums.h.in"
+ SOURCE_TEMPLATE "src/turns-enums.c.in"
+ OUTPUT_NAME "turns-enums"
+ HEADERS ${HEADERS}
+)
+
+enable_coverage("lib")
+
+install(TARGETS "lib"
+ FILE_SET HEADERS
+)
+
+# Tests
+
+add_executable("lib-tests"
+ "tests/runtime_init.cpp"
+ "tests/turns-participant.cpp"
+)
+
+target_link_libraries("lib-tests" PRIVATE
+ "Catch2::Catch2WithMain"
+
+ "turns::lib"
+)
+
+target_link_options("lib-tests" PRIVATE
+ "$<$<AND:$<CXX_COMPILER_ID:GNU,Clang>,$<CONFIG:Debug>>:--coverage>"
+)
+
+# file(GLOB_RECURSE TEST_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/tests" CONFIGURE_DEPENDS "*.trns")
+
+# target_add_glib_resources("core-tests"
+# PREFIX "/ch/arknet/Turns/core-tests/"
+# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests"
+# CSS_FILES ${TEST_FILES}
+# )
+
+catch_discover_tests("lib-tests") \ No newline at end of file
diff --git a/lib/src/turns-disposition.h b/lib/src/turns-disposition.h
new file mode 100644
index 0000000..c5bb174
--- /dev/null
+++ b/lib/src/turns-disposition.h
@@ -0,0 +1,18 @@
+#ifndef TURNS_DISPOSITION_H
+#define TURNS_DISPOSITION_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ TURNS_DISPOSITION_NEUTRAL,
+ TURNS_DISPOSITION_FRIENDLY,
+ TURNS_DISPOSITION_HOSTILE,
+ TURNS_DISPOSITION_SECRET,
+} TurnsDisposition;
+
+G_END_DECLS
+
+#endif
diff --git a/lib/src/turns-enums.c.in b/lib/src/turns-enums.c.in
new file mode 100644
index 0000000..2f75d77
--- /dev/null
+++ b/lib/src/turns-enums.c.in
@@ -0,0 +1,37 @@
+/*** BEGIN file-header ***/
+#include "turns-enums.h"
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@basename@" */
+#include "@basename@"
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+@enum_name@_get_type (void)
+{
+ static gsize static_g_@type@_type_id;
+
+ if (g_once_init_enter (&static_g_@type@_type_id))
+ {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+
+ GType g_@type@_type_id =
+ g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
+
+ g_once_init_leave (&static_g_@type@_type_id, g_@type@_type_id);
+ }
+ return static_g_@type@_type_id;
+}
+
+/*** END value-tail ***/
diff --git a/lib/src/turns-enums.h.in b/lib/src/turns-enums.h.in
new file mode 100644
index 0000000..de93e31
--- /dev/null
+++ b/lib/src/turns-enums.h.in
@@ -0,0 +1,25 @@
+/*** BEGIN file-header ***/
+#ifndef TURNS_ENUMS_H
+#define TURNS_ENUMS_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@basename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif
+/*** END file-tail ***/
diff --git a/lib/src/turns-init.cpp b/lib/src/turns-init.cpp
new file mode 100644
index 0000000..544dc14
--- /dev/null
+++ b/lib/src/turns-init.cpp
@@ -0,0 +1,17 @@
+#include "turns-init.h"
+
+#include "turns-enums.h"
+#include "turns-participant.h"
+
+#include <glib-object.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+auto turns_init() -> void
+{
+ g_type_ensure(TURNS_TYPE_PARTICIPANT);
+ g_type_ensure(TURNS_TYPE_DISPOSITION);
+}
+
+G_END_DECLS \ No newline at end of file
diff --git a/lib/src/turns-init.h b/lib/src/turns-init.h
new file mode 100644
index 0000000..a6e2013
--- /dev/null
+++ b/lib/src/turns-init.h
@@ -0,0 +1,12 @@
+#ifndef TURNS_INIT_H
+#define TURNS_INIT_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+void turns_init(void);
+
+G_END_DECLS
+
+#endif
diff --git a/lib/src/turns-participant.cpp b/lib/src/turns-participant.cpp
new file mode 100644
index 0000000..a820f3f
--- /dev/null
+++ b/lib/src/turns-participant.cpp
@@ -0,0 +1,202 @@
+#include "turns-participant.h"
+
+#include "turns-disposition.h"
+#include "turns-enums.h"
+
+#include <glib-object.h>
+#include <glib.h>
+#include <glibconfig.h>
+
+#include <array>
+#include <cstddef>
+#include <limits>
+
+G_BEGIN_DECLS
+
+struct _TurnsParticipant
+{
+ GObject parent_instance;
+
+ gchar * name;
+ gfloat priority;
+ TurnsDisposition disposition;
+};
+
+G_DEFINE_TYPE(TurnsParticipant, turns_participant, G_TYPE_OBJECT)
+
+G_END_DECLS
+
+namespace
+{
+ enum struct property
+ {
+ Name = 1,
+ Priority,
+ Disposition,
+ N_PROPERTIES,
+ };
+
+ auto static constinit properties = std::array<GParamSpec *, static_cast<std::size_t>(property::N_PROPERTIES)>{};
+
+ auto finalize(GObject * self)
+ {
+ auto participant = TURNS_PARTICIPANT(self);
+
+ g_free(participant->name);
+
+ G_OBJECT_CLASS(turns_participant_parent_class)->finalize(self);
+ }
+
+ auto get_property(GObject * self, guint id, GValue * value, GParamSpec * specification) -> void
+ {
+ auto participant = TURNS_PARTICIPANT(self);
+
+ switch (static_cast<property>(id))
+ {
+ case property::Name:
+ g_value_set_string(value, turns_participant_get_name(participant));
+ return;
+ case property::Priority:
+ g_value_set_float(value, turns_participant_get_priority(participant));
+ return;
+ case property::Disposition:
+ g_value_set_enum(value, turns_participant_get_disposition(participant));
+ return;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(self, id, specification);
+ };
+ }
+
+ auto set_property(GObject * self, guint id, GValue const * value, GParamSpec * specification) -> void
+ {
+ auto participant = TURNS_PARTICIPANT(self);
+
+ switch (static_cast<property>(id))
+ {
+ case property::Name:
+ return turns_participant_set_name(participant, g_value_get_string(value));
+ case property::Priority:
+ return turns_participant_set_priority(participant, g_value_get_float(value));
+ case property::Disposition:
+ return turns_participant_set_disposition(participant, static_cast<TurnsDisposition>(g_value_get_enum(value)));
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(self, id, specification);
+ }
+ }
+} // namespace
+
+G_BEGIN_DECLS
+
+static void turns_participant_class_init(TurnsParticipantClass * klass)
+{
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
+
+ (void)object_class;
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->finalize = finalize;
+
+ properties[static_cast<std::size_t>(property::Name)] =
+ g_param_spec_string("name",
+ "Name",
+ "The Name of the participant",
+ "",
+ static_cast<GParamFlags>(G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
+
+ properties[static_cast<std::size_t>(property::Priority)] =
+ g_param_spec_float("priority",
+ "Priority",
+ "The turn priority of the participant",
+ -std::numeric_limits<float>::infinity(),
+ +std::numeric_limits<float>::infinity(),
+ 0.0f,
+ static_cast<GParamFlags>(G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
+
+ properties[static_cast<std::size_t>(property::Disposition)] =
+ g_param_spec_enum("disposition",
+ "Disposition",
+ "Disposition of the participant toward the players",
+ turns_disposition_get_type(),
+ TURNS_DISPOSITION_NEUTRAL,
+ static_cast<GParamFlags>(G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
+
+ g_object_class_install_properties(object_class, static_cast<guint>(property::N_PROPERTIES), properties.data());
+}
+
+static void turns_participant_init(TurnsParticipant * self)
+{
+ (void)self;
+}
+
+TurnsParticipant * turns_participant_new()
+{
+ return static_cast<TurnsParticipant *>(g_object_new(TURNS_TYPE_PARTICIPANT, nullptr));
+}
+
+TurnsParticipant * turns_participant_new_with(gchar const * name, gfloat priority, TurnsDisposition disposition)
+{
+ g_return_val_if_fail(name != nullptr, nullptr);
+
+ return static_cast<TurnsParticipant *>(
+ g_object_new(TURNS_TYPE_PARTICIPANT, "name", name, "priority", priority, "disposition", static_cast<gint>(disposition), nullptr));
+}
+
+gchar const * turns_participant_get_name(TurnsParticipant const * self)
+{
+ g_return_val_if_fail(TURNS_IS_PARTICIPANT(const_cast<TurnsParticipant *>(self)), nullptr);
+ return self->name;
+}
+
+gfloat turns_participant_get_priority(TurnsParticipant const * self)
+{
+ g_return_val_if_fail(TURNS_IS_PARTICIPANT(const_cast<TurnsParticipant *>(self)), 0.0f);
+ return self->priority;
+}
+
+TurnsDisposition turns_participant_get_disposition(TurnsParticipant const * self)
+{
+ g_return_val_if_fail(TURNS_IS_PARTICIPANT(const_cast<TurnsParticipant *>(self)), TurnsDisposition::TURNS_DISPOSITION_NEUTRAL);
+ return self->disposition;
+}
+
+void turns_participant_set_name(TurnsParticipant * self, gchar const * value)
+{
+ g_return_if_fail(TURNS_IS_PARTICIPANT(self));
+ g_return_if_fail(value != nullptr);
+
+ if (!g_set_str(&self->name, value))
+ {
+ return;
+ }
+
+ g_object_notify_by_pspec(G_OBJECT(self), properties[static_cast<std::size_t>(property::Name)]);
+}
+
+void turns_participant_set_priority(TurnsParticipant * self, gfloat value)
+{
+ g_return_if_fail(TURNS_IS_PARTICIPANT(self));
+
+ if (value == self->priority)
+ {
+ return;
+ }
+
+ self->priority = value;
+ g_object_notify_by_pspec(G_OBJECT(self), properties[static_cast<std::size_t>(property::Priority)]);
+}
+
+void turns_participant_set_disposition(TurnsParticipant * self, TurnsDisposition value)
+{
+ g_return_if_fail(TURNS_IS_PARTICIPANT(self));
+
+ if (value == self->disposition)
+ {
+ return;
+ }
+
+ self->disposition = value;
+ g_object_notify_by_pspec(G_OBJECT(self), properties[static_cast<std::size_t>(property::Disposition)]);
+}
+
+G_END_DECLS
diff --git a/lib/src/turns-participant.h b/lib/src/turns-participant.h
new file mode 100644
index 0000000..502de32
--- /dev/null
+++ b/lib/src/turns-participant.h
@@ -0,0 +1,84 @@
+#ifndef TURNS_PARTICIPANT_H
+#define TURNS_PARTICIPANT_H
+
+#include "turns-disposition.h"
+
+#include <glib-object.h>
+#include <glib.h>
+#include <glibconfig.h>
+
+G_BEGIN_DECLS
+
+#define TURNS_TYPE_PARTICIPANT turns_participant_get_type()
+G_DECLARE_FINAL_TYPE(TurnsParticipant, turns_participant, TURNS, PARTICIPANT, GObject)
+
+/**
+ * @brief Construct a new Participant.
+ *
+ * This functions constructs a default initialized instance, meaning:
+ * - @p name is the empty string
+ * - @p priority is 0.0f
+ * - @p disposition is Disposition.Neutral.
+ */
+TurnsParticipant * turns_participant_new() G_GNUC_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Construct a new Participant with the given values.
+ *
+ * @param name The name of the new instance. The value *must not* be NULL.
+ * @param priority The priority of the new instance.
+ * @param disposition The disposition of the new instance.
+ */
+TurnsParticipant * turns_participant_new_with(gchar const * name, gfloat priority, TurnsDisposition disposition) G_GNUC_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Get the name of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @return The name of the instance. The data is owned by the instance.
+ */
+gchar const * turns_participant_get_name(TurnsParticipant const * self);
+
+/**
+ * @brief Get the priority of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @return The priority of the instance.
+ */
+gfloat turns_participant_get_priority(TurnsParticipant const * self);
+
+/**
+ * @brief Get the disposition of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @return The disposition of the instance.
+ */
+TurnsDisposition turns_participant_get_disposition(TurnsParticipant const * self);
+
+/**
+ * @brief Set the name of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @param value The new name. The data is owned by the caller of the method.
+ */
+void turns_participant_set_name(TurnsParticipant * self, gchar const * value);
+
+/**
+ * @brief Set the priority of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @param value The new priority.
+ */
+void turns_participant_set_priority(TurnsParticipant * self, gfloat value);
+
+/**
+ * @brief Set the disposition of a participant.
+ *
+ * @param self A Participant instance. The value *must not* be NULL.
+ * @param value The new disposition.
+ */
+void turns_participant_set_disposition(TurnsParticipant * self, TurnsDisposition value);
+
+G_END_DECLS
+
+#endif \ No newline at end of file
diff --git a/lib/tests/runtime_init.cpp b/lib/tests/runtime_init.cpp
new file mode 100644
index 0000000..189ef35
--- /dev/null
+++ b/lib/tests/runtime_init.cpp
@@ -0,0 +1,21 @@
+#include "turns-init.h"
+
+#include <catch2/reporters/catch_reporter_event_listener.hpp>
+#include <catch2/reporters/catch_reporter_registrars.hpp>
+
+namespace turns::core::tests
+{
+
+ struct glib_test_init : Catch::EventListenerBase
+ {
+ using Catch::EventListenerBase::EventListenerBase;
+
+ auto testRunStarting(Catch::TestRunInfo const &) -> void override
+ {
+ turns_init();
+ }
+ };
+
+ CATCH_REGISTER_LISTENER(glib_test_init);
+
+} // namespace turns::core::tests \ No newline at end of file
diff --git a/lib/tests/turns-participant.cpp b/lib/tests/turns-participant.cpp
new file mode 100644
index 0000000..89e60cf
--- /dev/null
+++ b/lib/tests/turns-participant.cpp
@@ -0,0 +1,353 @@
+#include "turns-participant.h"
+
+#include "turns-disposition.h"
+
+#include <catch2/catch_approx.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/generators/catch_generators.hpp>
+
+#include <glib-object.h>
+#include <glib.h>
+
+#include <string>
+
+namespace
+{
+ auto record_notification(TurnsParticipant const *, GParamSpec *, bool * out) -> void
+ {
+ *out = true;
+ }
+} // namespace
+
+SCENARIO("Creating a participant", "[lib][object][lifetime]")
+{
+ GIVEN("A participant constructed using turns_participant_new()")
+ {
+ g_autoptr(TurnsParticipant) instance = turns_participant_new();
+
+ THEN("it's name is empty")
+ {
+ auto name = turns_participant_get_name(instance);
+ REQUIRE(name);
+ REQUIRE(std::string{name}.empty());
+ }
+
+ THEN("it's priority is 0.0f")
+ {
+ REQUIRE(turns_participant_get_priority(instance) == Catch::Approx{0.0});
+ }
+
+ THEN("it's disposition is neutral")
+ {
+ REQUIRE(turns_participant_get_disposition(instance) == TURNS_DISPOSITION_NEUTRAL);
+ }
+ }
+
+ GIVEN("A participant constructed using turns_participant_new_with(...)")
+ {
+ auto name = "Test Participant";
+ auto priority = 12.4f;
+ auto disposition = TURNS_DISPOSITION_FRIENDLY;
+ g_autoptr(TurnsParticipant) instance = turns_participant_new_with(name, priority, disposition);
+
+ THEN("it's name is set")
+ {
+ REQUIRE(turns_participant_get_name(instance) == std::string{name});
+ }
+
+ THEN("it's priority is set")
+ {
+ REQUIRE(turns_participant_get_priority(instance) == Catch::Approx{priority});
+ }
+
+ THEN("it's disposition is")
+ {
+ REQUIRE(turns_participant_get_disposition(instance) == disposition);
+ }
+ }
+
+ GIVEN("A participant is constructed using turns_participant_new_with(nullptr, ...)")
+ {
+ auto instance = turns_participant_new_with(nullptr, 10.0f, TURNS_DISPOSITION_HOSTILE);
+
+ THEN("the instance is NULL")
+ {
+ REQUIRE(instance == nullptr);
+ }
+ }
+}
+
+SCENARIO("Modifying a participant", "[lib][object][data]")
+{
+ GIVEN("A default participant instance")
+ {
+ g_autoptr(TurnsParticipant) instance = turns_participant_new();
+
+ WHEN("a new new is set")
+ {
+ auto new_value = "Test Participant";
+
+ CHECK(std::string{turns_participant_get_name(instance)}.empty());
+ CHECK_FALSE(std::string{turns_participant_get_name(instance)} == new_value);
+ turns_participant_set_name(instance, new_value);
+
+ THEN("it's name is not empty")
+ {
+ REQUIRE_FALSE(std::string{turns_participant_get_name(instance)}.empty());
+ }
+
+ THEN("it's name has the new value")
+ {
+ REQUIRE(std::string{turns_participant_get_name(instance)} == new_value);
+ }
+ }
+
+ WHEN("a new priority is set")
+ {
+ auto new_value = GENERATE(-8.0f, 12.0f, 4.0f);
+
+ CHECK_FALSE(turns_participant_get_priority(instance) == new_value);
+ turns_participant_set_priority(instance, new_value);
+
+ THEN("it's priority has the new value")
+ {
+ REQUIRE(turns_participant_get_priority(instance) == Catch::Approx{new_value});
+ }
+ }
+
+ WHEN("a new disposition is set")
+ {
+ auto new_value = GENERATE(TURNS_DISPOSITION_FRIENDLY, TURNS_DISPOSITION_HOSTILE, TURNS_DISPOSITION_SECRET);
+
+ CHECK_FALSE(turns_participant_get_disposition(instance) == new_value);
+ turns_participant_set_disposition(instance, new_value);
+
+ THEN("it's disposition has the new value")
+ {
+ REQUIRE(turns_participant_get_disposition(instance) == new_value);
+ }
+ }
+
+ AND_GIVEN("a signal handler has been subscribed to the name property")
+ {
+ auto was_notified = false;
+ g_signal_connect(instance, "notify::name", G_CALLBACK(&record_notification), &was_notified);
+
+ WHEN("a new name is set using set_name")
+ {
+ auto new_value = "Test Participant";
+
+ CHECK_FALSE(std::string{turns_participant_get_name(instance)} == new_value);
+ turns_participant_set_name(instance, new_value);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same name is set using set_name")
+ {
+ auto new_value = turns_participant_get_name(instance);
+
+ CHECK(std::string{turns_participant_get_name(instance)} == new_value);
+ turns_participant_set_name(instance, new_value);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+
+ WHEN("a new name is set using g_object_set")
+ {
+ auto new_value = "Test Participant";
+
+ CHECK_FALSE(std::string{turns_participant_get_name(instance)} == new_value);
+ g_object_set(G_OBJECT(instance), "name", new_value, nullptr);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same name is set using g_object_set")
+ {
+ auto new_value = turns_participant_get_name(instance);
+
+ CHECK(std::string{turns_participant_get_name(instance)} == new_value);
+ g_object_set(G_OBJECT(instance), "name", new_value, nullptr);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+ }
+
+ AND_GIVEN("a signal handler has been subscribed to the priority property")
+ {
+ auto was_notified = false;
+ g_signal_connect(instance, "notify::priority", G_CALLBACK(&record_notification), &was_notified);
+
+ WHEN("a new priority is set using set_priority")
+ {
+ auto new_value = 17.15;
+
+ CHECK_FALSE(turns_participant_get_priority(instance) == new_value);
+ turns_participant_set_priority(instance, new_value);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same priority is set using set_priority")
+ {
+ auto new_value = turns_participant_get_priority(instance);
+
+ CHECK(turns_participant_get_priority(instance) == new_value);
+ turns_participant_set_priority(instance, new_value);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+
+ WHEN("a new priority is set using g_object_set")
+ {
+ auto new_value = 17.15;
+
+ CHECK_FALSE(turns_participant_get_priority(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "priority", new_value, nullptr);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same priority is set using g_object_set")
+ {
+ auto new_value = turns_participant_get_priority(instance);
+
+ CHECK(turns_participant_get_priority(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "priority", new_value, nullptr);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+ }
+
+ AND_GIVEN("a signal handler has been subscribed to the disposition property")
+ {
+ auto was_notified = false;
+ g_signal_connect(instance, "notify::disposition", G_CALLBACK(&record_notification), &was_notified);
+
+ WHEN("a new disposition is set using set_disposition")
+ {
+ auto new_value = TURNS_DISPOSITION_HOSTILE;
+
+ CHECK_FALSE(turns_participant_get_disposition(instance) == new_value);
+ turns_participant_set_disposition(instance, new_value);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same disposition is set using set_disposition")
+ {
+ auto new_value = turns_participant_get_disposition(instance);
+
+ CHECK(turns_participant_get_disposition(instance) == new_value);
+ turns_participant_set_disposition(instance, new_value);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+
+ WHEN("a new disposition is set using g_object_set")
+ {
+ auto new_value = TURNS_DISPOSITION_HOSTILE;
+
+ CHECK_FALSE(turns_participant_get_disposition(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "disposition", new_value, nullptr);
+
+ THEN("a notification is issued")
+ {
+ REQUIRE(was_notified);
+ }
+ }
+
+ WHEN("the same disposition is set using g_object_set")
+ {
+ auto new_value = turns_participant_get_disposition(instance);
+
+ CHECK(turns_participant_get_disposition(instance) == new_value);
+ g_object_set(G_OBJECT(instance), "disposition", new_value, nullptr);
+
+ THEN("no notification is issued")
+ {
+ REQUIRE_FALSE(was_notified);
+ }
+ }
+ }
+ }
+}
+
+SCENARIO("Reading a participant", "[lib][object][data]")
+{
+ GIVEN("A participant with a set name, priority, and disposition")
+ {
+ auto name = "Test Participant";
+ auto priority = 75.f;
+ auto disposition = TURNS_DISPOSITION_FRIENDLY;
+
+ g_autoptr(TurnsParticipant) instance = turns_participant_new_with(name, priority, disposition);
+
+ WHEN("reading the name via get_name and g_object_get")
+ {
+ auto getter_value = turns_participant_get_name(instance);
+ g_autofree auto property_value = decltype(turns_participant_get_name(instance)){};
+ g_object_get(instance, "name", &property_value, nullptr);
+
+ THEN("they both compare equal")
+ {
+ REQUIRE(std::string{getter_value} == property_value);
+ }
+ }
+
+ WHEN("reading the priority via get_priority and g_object_get")
+ {
+ auto getter_value = turns_participant_get_priority(instance);
+ auto property_value = decltype(turns_participant_get_priority(instance)){};
+ g_object_get(instance, "priority", &property_value, nullptr);
+
+ THEN("they both compare equal")
+ {
+ REQUIRE(getter_value == property_value);
+ }
+ }
+
+ WHEN("reading the disposition via get_disposition and g_object_get")
+ {
+ auto getter_value = turns_participant_get_disposition(instance);
+ auto property_value = decltype(turns_participant_get_disposition(instance)){};
+ g_object_get(instance, "disposition", &property_value, nullptr);
+
+ THEN("they both compare equal")
+ {
+ REQUIRE(getter_value == property_value);
+ }
+ }
+ }
+} \ No newline at end of file