[glibmm/wip/dboles/Binding-2.62: 3/4] tests/glibmm_binding: Add basic test inc transform



commit e22129192be7a0f3cfc795495f6397330cf8b007
Author: Daniel Boles <dboles src gmail com>
Date:   Sat Nov 9 15:07:09 2019 +0000

    tests/glibmm_binding: Add basic test inc transform
    
    A basic test is better than nothing, and I propose to change how the
    transform function works so want to be fully confident it still does.

 tests/Makefile.am            |   2 +
 tests/glibmm_binding/main.cc | 116 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 895d205c..b898575b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -27,6 +27,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    \
@@ -90,6 +91,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..cdbcaf7b
--- /dev/null
+++ b/tests/glibmm_binding/main.cc
@@ -0,0 +1,116 @@
+#include <glib.h>
+#include <glibmm/binding.h>
+#include <glibmm/init.h>
+#include <glibmm/object.h>
+#include <glibmm/property.h>
+#include <glibmm/propertyproxy.h>
+
+#include <limits>
+
+namespace {
+
+class StringSource final: public Glib::Object {
+public:
+  StringSource(): Glib::ObjectBase{"StringSource"} {}
+
+  auto property_string() -> Glib::PropertyProxy<Glib::ustring>
+    { 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() -> Glib::PropertyProxy<int>
+    { return m_property_int.get_proxy(); }
+
+private:
+  Glib::Property<int> m_property_int{*this, "int"};
+};
+
+template <typename T>
+auto
+clamp(const T& t, const T& min, const T& max) -> const T&
+{
+  return t < min ? min : t > max ? max : t;
+}
+
+auto
+transform_string_to_int(const Glib::ustring& source, int& target) -> bool
+{
+  char* str_end{};
+  auto long_int = std::strtol(source.c_str(), &str_end, 10);
+
+  if (str_end == source.c_str())
+    return false;
+
+  using IntLimits = std::numeric_limits<int>;
+  auto constexpr min = long{IntLimits::min()};
+  auto constexpr max = long{IntLimits::max()};
+  auto const clamped_int = clamp(long_int, min, max);
+
+  if (clamped_int != long_int)
+    return false;
+
+  target = static_cast<int>(clamped_int);
+  return true;
+}
+
+void
+test()
+{
+  Glib::init();
+  StringSource source{};
+  IntTarget target{};
+
+  // 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_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_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;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]