diff options
author | Daniel Boles <dboles.src@gmail.com> | 2019-11-09 15:09:06 +0000 |
---|---|---|
committer | Daniel Boles <dboles@src.gnome.org> | 2019-11-09 20:04:18 +0000 |
commit | 5f9dc06c18f6f8ed65d7e2035b21bbc2df751a43 (patch) | |
tree | 711987d05aa3b6e3e0bb92b112c0c8562af36bea /tests | |
parent | a429221b4c15b004409c6f4ab0549b9740851148 (diff) | |
download | glibmm-5f9dc06c18f6f8ed65d7e2035b21bbc2df751a43.tar.gz |
tests/glibmm_binding: Add basic test inc transform
A basic test is better than nothing, and I just changed how the
transform function works and want to be confident it still does.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/glibmm_binding/main.cc | 106 |
2 files changed, 108 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 3f6f81c9..3905c52f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,6 +28,7 @@ check_PROGRAMS = \ giomm_listmodel/test \ glibmm_btree/test \ glibmm_base64/test \ + glibmm_binding/test \ glibmm_date/test \ glibmm_buildfilename/test \ glibmm_interface_implementation/test \ @@ -92,6 +93,7 @@ giomm_listmodel_test_SOURCES = giomm_listmodel/main.cc giomm_listmodel_test_LDADD = $(giomm_ldadd) glibmm_base64_test_SOURCES = glibmm_base64/main.cc +glibmm_binding_test_SOURCES = glibmm_binding/main.cc glibmm_btree_test_SOURCES = glibmm_btree/main.cc glibmm_buildfilename_test_SOURCES = glibmm_buildfilename/main.cc glibmm_date_test_SOURCES = glibmm_date/main.cc diff --git a/tests/glibmm_binding/main.cc b/tests/glibmm_binding/main.cc new file mode 100644 index 00000000..9b727e51 --- /dev/null +++ b/tests/glibmm_binding/main.cc @@ -0,0 +1,106 @@ +#include <glib.h> +#include <glibmm/binding.h> +#include <glibmm/init.h> +#include <glibmm/object.h> +#include <glibmm/property.h> +#include <glibmm/propertyproxy.h> + +#include <algorithm> +#include <limits> + +namespace { + +class StringSource final: public Glib::Object { +public: + StringSource(): Glib::ObjectBase{"StringSource"} {} + auto property_string() { return m_property_string.get_proxy(); } + +private: + Glib::Property<Glib::ustring> m_property_string{*this, "string"}; +}; + +class IntTarget final: public Glib::Object { +public: + IntTarget(): Glib::ObjectBase{"IntTarget"} {} + auto property_int() { return m_property_int.get_proxy(); } + +private: + Glib::Property<int> m_property_int{*this, "int"}; +}; + +auto +transform_string_to_int(const Glib::ustring& source) -> std::optional<int> +{ + char* str_end{}; + auto long_int = std::strtol(source.c_str(), &str_end, 10); + + if (str_end == source.c_str()) + return std::nullopt; + + using IntLimits = std::numeric_limits<int>; + auto constexpr min = long{IntLimits::min()}; + auto constexpr max = long{IntLimits::max()}; + auto const clamped_int = std::clamp(long_int, min, max); + + if (clamped_int != long_int) + return std::nullopt; + + return static_cast<int>(clamped_int); +} + +void +test() +{ + Glib::init(); + + auto source = StringSource{}; + auto target = IntTarget{}; + + // We should obviously not change the target before it has been bound! + target.property_int() = 7; + source.property_string() = "42"; + g_assert_cmpint(target.property_int(), ==, 7); + + { + auto binding = Glib::Binding::bind_property( + source.property_string(), target.property_int(), + Glib::Binding::Flags::DEFAULT, &transform_string_to_int); + + // Without SYNC_CREATE, only changes after bound will be synced + g_assert_cmpint(target.property_int(), ==, 7); + + // An empty string is not a zero + source.property_string() = ""; + g_assert_cmpint(target.property_int(), ==, 7); + + // Ensure the change is synced + source.property_string() = "47"; + g_assert_cmpint(target.property_int(), ==, 47); + + // Ensure no change when invalid source results in false return + source.property_string() = "six six six"; + g_assert_cmpint(target.property_int(), ==, 47); + } + + // Ensure the binding was released when its RefPtr went out of scope + source.property_string() = "89"; + g_assert_cmpint(target.property_int(), ==, 47); + + { + auto binding = Glib::Binding::bind_property( + source.property_string(), target.property_int(), + Glib::Binding::Flags::SYNC_CREATE, &transform_string_to_int); + + // With SYNC_CREATE, value of source must sync to target on bind + g_assert_cmpint(target.property_int(), ==, 89); + } +} + +} // namespace + +auto +main() -> int +{ + test(); + return 0; +} |