[gtk/wip/otte/listview: 147/158] Add some tests for expression binding



commit cc98a076347fc157f2c656d7feb54b227eb9796d
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Dec 14 15:36:34 2019 -0500

    Add some tests for expression binding
    
    In particular, test that expressios can deal with object == this.

 testsuite/gtk/expression.c | 305 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 305 insertions(+)
---
diff --git a/testsuite/gtk/expression.c b/testsuite/gtk/expression.c
index 663e0fcbaf..d8c75e527b 100644
--- a/testsuite/gtk/expression.c
+++ b/testsuite/gtk/expression.c
@@ -412,6 +412,304 @@ test_constant_watch_this_destroyed (void)
 
   g_clear_object (&this);
   g_assert_cmpint (counter, ==, 1);
+
+  gtk_expression_unref (expr);
+}
+
+/* Basic test of gtk_expression_bind */
+static void
+test_bind (void)
+{
+  GtkFilter *target;
+  GtkFilter *source;
+  GtkExpression *expr;
+  GtkExpressionWatch *watch;
+  GValue value = G_VALUE_INIT;
+  gboolean res;
+
+  expr = gtk_property_expression_new (GTK_TYPE_STRING_FILTER, NULL, "search");
+
+  target = gtk_string_filter_new ();
+  gtk_string_filter_set_search (GTK_STRING_FILTER (target), "word");
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (target)), ==, "word");
+
+  source = gtk_string_filter_new ();
+  gtk_string_filter_set_search (GTK_STRING_FILTER (source), "sausage");
+
+  watch = gtk_expression_bind (expr, target, "search", source);
+  gtk_expression_watch_ref (watch);
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (target)), ==, "sausage");
+
+  gtk_string_filter_set_search (GTK_STRING_FILTER (source), "salad");
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (target)), ==, "salad");
+  res = gtk_expression_watch_evaluate (watch, &value);
+  g_assert_true (res);
+  g_assert_cmpstr (g_value_get_string (&value), ==, "salad"); 
+  g_value_unset (&value);
+
+  g_object_unref (source);
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (target)), ==, "salad");
+  res = gtk_expression_watch_evaluate (watch, &value);
+  g_assert_false (res);
+  g_assert_false (G_IS_VALUE (&value));
+
+  g_object_unref (target);
+  gtk_expression_watch_unref (watch);
+}
+
+/* Another test of bind, this time we watch ourselves */
+static void
+test_bind_self (void)
+{
+  GtkFilter *filter;
+  GtkExpression *expr;
+
+  expr = gtk_property_expression_new (GTK_TYPE_STRING_FILTER,
+                                      NULL,
+                                      "ignore-case");
+
+  filter = gtk_string_filter_new ();
+  gtk_string_filter_set_search (GTK_STRING_FILTER (filter), "word");
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter)), ==, "word");
+
+  gtk_expression_bind (expr, filter, "search", filter);
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter)), ==, "TRUE");
+
+  g_object_unref (filter);
+}
+
+/* Test bind does the right memory management if the target's
+ * dispose() kills the source */
+static void
+test_bind_child (void)
+{
+  GtkFilter *filter;
+  GtkFilterListModel *child, *target;
+  GtkExpression *expr;
+
+  expr = gtk_property_expression_new (GTK_TYPE_FILTER_LIST_MODEL,
+                                      NULL,
+                                      "filter");
+
+  filter = gtk_string_filter_new ();
+  child = gtk_filter_list_model_new_for_type (G_TYPE_OBJECT);
+  gtk_filter_list_model_set_filter (child, filter);
+  target = gtk_filter_list_model_new (G_LIST_MODEL (child), NULL);
+  g_object_unref (child);
+  g_object_unref (filter);
+
+  gtk_expression_bind (expr, target, "filter", child);
+  g_assert_true (gtk_filter_list_model_get_filter (child) == gtk_filter_list_model_get_filter (target));
+
+  filter = gtk_string_filter_new ();
+  gtk_filter_list_model_set_filter (child, filter);
+  g_assert_true (filter == gtk_filter_list_model_get_filter (target));
+  g_assert_true (gtk_filter_list_model_get_filter (child) == gtk_filter_list_model_get_filter (target));
+  g_object_unref (filter);
+
+  g_object_unref (target);
+}
+
+/* Another test of gtk_expression_bind that exercises the subwatch code paths */
+static void
+test_nested_bind (void)
+{
+  GtkFilter *filter;
+  GtkFilter *filter2;
+  GtkFilter *filter3;
+  GListModel *list;
+  GtkFilterListModel *filtered;
+  GtkExpression *expr;
+  GtkExpression *filter_expr;
+  gboolean res;
+  GValue value = G_VALUE_INIT;
+
+  filter2 = gtk_string_filter_new ();
+  gtk_string_filter_set_search (GTK_STRING_FILTER (filter2), "sausage");
+
+  list = G_LIST_MODEL (g_list_store_new (G_TYPE_OBJECT));
+  filtered = gtk_filter_list_model_new (list, filter2);
+
+  filter_expr = gtk_property_expression_new (GTK_TYPE_FILTER_LIST_MODEL,
+                                             gtk_object_expression_new (G_OBJECT (filtered)),
+                                             "filter");
+  expr = gtk_property_expression_new (GTK_TYPE_STRING_FILTER, gtk_expression_ref (filter_expr), "search");
+
+  filter = gtk_string_filter_new ();
+  gtk_string_filter_set_search (GTK_STRING_FILTER (filter), "word");
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter)), ==, "word");
+
+  gtk_expression_bind (gtk_expression_ref (expr), filter, "search", NULL);
+
+  gtk_string_filter_set_search (GTK_STRING_FILTER (filter2), "sausage");
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter)), ==, "sausage");
+
+  filter3 = gtk_string_filter_new ();
+  gtk_string_filter_set_search (GTK_STRING_FILTER (filter3), "banana");
+  gtk_filter_list_model_set_filter (filtered, filter3);
+
+  /* check that the expressions evaluate correctly */
+  res = gtk_expression_evaluate (filter_expr, NULL, &value);
+  g_assert_true (res);
+  g_assert (g_value_get_object (&value) == filter3);
+  g_value_unset (&value);
+
+  res = gtk_expression_evaluate (expr, NULL, &value);
+  g_assert_true (res);
+  g_assert_cmpstr (g_value_get_string (&value), ==, "banana");
+  g_value_unset (&value);
+
+  /* and the bind too */
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter)), ==, "banana");
+
+  g_object_unref (filter);
+  g_object_unref (filter2);
+  g_object_unref (filter3);
+  g_object_unref (filtered);
+  g_object_unref (list);
+
+  gtk_expression_unref (expr);
+  gtk_expression_unref (filter_expr);
+}
+
+static char *
+some_cb (gpointer    this,
+         const char *search,
+         gboolean    ignore_case,
+         gpointer    data)
+{
+  if (!search)
+    return NULL;
+
+  if (ignore_case)
+    return g_utf8_strdown (search, -1);
+  else
+    return g_strdup (search);
+}
+
+/* Test that things work as expected when the same object is used multiple times in an
+ * expression or its subexpressions.
+ */
+static void
+test_double_bind (void)
+{
+  GtkStringFilter *filter1;
+  GtkStringFilter *filter2;
+  GtkExpression *expr;
+  GtkExpression *filter_expr;
+  GtkExpression *params[2];
+
+  filter1 = GTK_STRING_FILTER (gtk_string_filter_new ());
+  filter2 = GTK_STRING_FILTER (gtk_string_filter_new ());
+
+  filter_expr = gtk_object_expression_new (G_OBJECT (filter1));
+
+  params[0] = gtk_property_expression_new (GTK_TYPE_STRING_FILTER, gtk_expression_ref (filter_expr), 
"search");
+  params[1] = gtk_property_expression_new (GTK_TYPE_STRING_FILTER, gtk_expression_ref (filter_expr), 
"ignore-case");
+  expr = gtk_cclosure_expression_new (G_TYPE_STRING,
+                                      NULL,
+                                      2, params,
+                                      (GCallback)some_cb,
+                                      NULL, NULL);
+
+  gtk_expression_bind (gtk_expression_ref (expr), filter2, "search", NULL);
+
+  gtk_string_filter_set_search (GTK_STRING_FILTER (filter1), "Banana");
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter2)), ==, "banana");
+
+  gtk_string_filter_set_ignore_case (GTK_STRING_FILTER (filter1), FALSE);
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter2)), ==, "Banana");
+
+  gtk_expression_unref (expr);
+  gtk_expression_unref (filter_expr);
+
+  g_object_unref (filter1);
+  g_object_unref (filter2);
+}
+
+/* Test that having multiple binds on the same object works. */
+static void
+test_binds (void)
+{
+  GtkStringFilter *filter1;
+  GtkStringFilter *filter2;
+  GtkStringFilter *filter3;
+  GtkExpression *expr;
+  GtkExpression *expr2;
+  GtkExpression *filter1_expr;
+  GtkExpression *filter2_expr;
+  GtkExpression *params[2];
+
+  filter1 = GTK_STRING_FILTER (gtk_string_filter_new ());
+  filter2 = GTK_STRING_FILTER (gtk_string_filter_new ());
+  filter3 = GTK_STRING_FILTER (gtk_string_filter_new ());
+
+  filter1_expr = gtk_object_expression_new (G_OBJECT (filter1));
+  filter2_expr = gtk_object_expression_new (G_OBJECT (filter2));
+
+  params[0] = gtk_property_expression_new (GTK_TYPE_STRING_FILTER, gtk_expression_ref (filter1_expr), 
"search");
+  params[1] = gtk_property_expression_new (GTK_TYPE_STRING_FILTER, gtk_expression_ref (filter2_expr), 
"ignore-case");
+  expr = gtk_cclosure_expression_new (G_TYPE_STRING,
+                                      NULL,
+                                      2, params,
+                                      (GCallback)some_cb,
+                                      NULL, NULL);
+
+  expr2 = gtk_property_expression_new (GTK_TYPE_STRING_FILTER, gtk_expression_ref (filter2_expr), 
"ignore-case");
+
+  gtk_expression_bind (gtk_expression_ref (expr), filter3, "search", NULL);
+  gtk_expression_bind (gtk_expression_ref (expr2), filter3, "ignore-case", NULL);
+
+  gtk_string_filter_set_search (GTK_STRING_FILTER (filter1), "Banana");
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter3)), ==, "banana");
+  g_assert_true (gtk_string_filter_get_ignore_case (GTK_STRING_FILTER (filter3)));
+
+  gtk_string_filter_set_ignore_case (GTK_STRING_FILTER (filter2), FALSE);
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter3)), ==, "Banana");
+  g_assert_false (gtk_string_filter_get_ignore_case (GTK_STRING_FILTER (filter3)));
+
+  /* invalidate the first bind */
+  g_object_unref (filter1);
+
+  gtk_string_filter_set_ignore_case (GTK_STRING_FILTER (filter2), TRUE);
+  g_assert_cmpstr (gtk_string_filter_get_search (GTK_STRING_FILTER (filter3)), ==, "Banana");
+  g_assert_true (gtk_string_filter_get_ignore_case (GTK_STRING_FILTER (filter3)));
+
+  gtk_expression_unref (expr);
+  gtk_expression_unref (expr2);
+  gtk_expression_unref (filter1_expr);
+  gtk_expression_unref (filter2_expr);
+
+  g_object_unref (filter2);
+  g_object_unref (filter3);
+}
+
+/* test that binds work ok with object expressions */
+static void
+test_bind_object (void)
+{
+  GtkFilter *filter;
+  GListStore *store;
+  GtkFilterListModel *model;
+  GtkExpression *expr;
+
+  filter = gtk_string_filter_new ();
+  store = g_list_store_new (G_TYPE_OBJECT);
+  model = gtk_filter_list_model_new (G_LIST_MODEL (store), NULL);
+
+  expr = gtk_object_expression_new (G_OBJECT (filter));
+
+  gtk_expression_bind (gtk_expression_ref (expr), model, "filter", NULL);
+
+  g_assert_true (gtk_filter_list_model_get_filter (model) == filter);
+
+  g_object_unref (filter);
+
+  g_assert_true (gtk_filter_list_model_get_filter (model) == filter);
+
+  gtk_expression_unref (expr);
+  g_object_unref (model);
+  g_object_unref (store);
 }
 
 int
@@ -429,6 +727,13 @@ main (int argc, char *argv[])
   g_test_add_func ("/expression/nested-this-destroyed", test_nested_this_destroyed);
   g_test_add_func ("/expression/type-mismatch", test_type_mismatch);
   g_test_add_func ("/expression/this", test_this);
+  g_test_add_func ("/expression/bind", test_bind);
+  g_test_add_func ("/expression/bind-self", test_bind_self);
+  g_test_add_func ("/expression/bind-child", test_bind_child);
+  g_test_add_func ("/expression/nested-bind", test_nested_bind);
+  g_test_add_func ("/expression/double-bind", test_double_bind);
+  g_test_add_func ("/expression/binds", test_binds);
+  g_test_add_func ("/expression/bind-object", test_bind_object);
 
   return g_test_run ();
 }


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