]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
test: Exercise successful and failed RemoveMatch calls
authorSimon McVittie <smcv@collabora.com>
Mon, 22 Nov 2021 15:58:40 +0000 (15:58 +0000)
committerSimon McVittie <smcv@collabora.com>
Mon, 22 Nov 2021 16:10:51 +0000 (16:10 +0000)
Reproduces: https://gitlab.freedesktop.org/dbus/dbus/-/issues/351
Signed-off-by: Simon McVittie <smcv@collabora.com>
test/dbus-daemon.c

index e8bdace3c7623eba11f6a2005af85db5b60c17cb..e57fcfa9cd1acb7fdddb7c05963e845807ba689e 100644 (file)
@@ -100,6 +100,7 @@ typedef struct {
     gchar *address;
 
     DBusConnection *left_conn;
+    gboolean left_conn_shouted_signal_filter;
 
     DBusConnection *right_conn;
     GQueue held_messages;
@@ -107,6 +108,7 @@ typedef struct {
     gboolean right_conn_hold;
     gboolean wait_forever_called;
     guint activation_forking_counter;
+    guint signal_counter;
 
     gchar *tmp_runtime_dir;
     gchar *saved_runtime_dir;
@@ -158,6 +160,19 @@ hold_filter (DBusConnection *connection,
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
+static DBusHandlerResult
+shouted_signal_filter (DBusConnection *connection,
+                       DBusMessage *message,
+                       void *user_data)
+{
+  Fixture *f = user_data;
+
+  if (dbus_message_is_signal (message, "com.example", "Shouted"))
+    f->signal_counter++;
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
 typedef struct {
     const char *bug_ref;
     guint min_messages;
@@ -236,6 +251,31 @@ add_hold_filter (Fixture *f)
   f->right_conn_hold = TRUE;
 }
 
+static void
+add_shouted_signal_filter (Fixture *f)
+{
+  if (!dbus_connection_add_filter (f->left_conn, shouted_signal_filter, f, NULL))
+    g_error ("OOM");
+
+  f->left_conn_shouted_signal_filter = TRUE;
+}
+
+static void
+right_conn_emit_shouted (Fixture *f)
+{
+  DBusMessage *m;
+
+  m = dbus_message_new_signal ("/", "com.example", "Shouted");
+
+  if (m == NULL)
+    g_error ("OOM");
+
+  if (!dbus_connection_send (f->right_conn, m, NULL))
+    g_error ("OOM");
+
+  dbus_clear_message (&m);
+}
+
 static void
 pc_count (DBusPendingCall *pc,
     void *data)
@@ -257,30 +297,11 @@ pc_enqueue (DBusPendingCall *pc,
 }
 
 static void
-test_echo (Fixture *f,
-    gconstpointer context)
+echo_left_to_right (Fixture *f,
+                    guint count)
 {
-  const Config *config = context;
-  guint count = 2000;
   guint sent;
   guint received = 0;
-  double elapsed;
-
-  if (f->skip)
-    return;
-
-  if (config != NULL && config->bug_ref != NULL)
-    g_test_bug (config->bug_ref);
-
-  if (g_test_perf ())
-    count = 100000;
-
-  if (config != NULL)
-    count = MAX (config->min_messages, count);
-
-  add_echo_filter (f);
-
-  g_test_timer_start ();
 
   for (sent = 0; sent < count; sent++)
     {
@@ -309,6 +330,33 @@ test_echo (Fixture *f,
 
   while (received < count)
     test_main_context_iterate (f->ctx, TRUE);
+}
+
+static void
+test_echo (Fixture *f,
+    gconstpointer context)
+{
+  const Config *config = context;
+  guint count = 2000;
+  double elapsed;
+
+  if (f->skip)
+    return;
+
+  if (config != NULL && config->bug_ref != NULL)
+    g_test_bug (config->bug_ref);
+
+  if (g_test_perf ())
+    count = 100000;
+
+  if (config != NULL)
+    count = MAX (config->min_messages, count);
+
+  add_echo_filter (f);
+
+  g_test_timer_start ();
+
+  echo_left_to_right (f, count);
 
   elapsed = g_test_timer_elapsed ();
 
@@ -2535,6 +2583,12 @@ teardown (Fixture *f,
 
   if (f->left_conn != NULL)
     {
+      if (f->left_conn_shouted_signal_filter)
+        {
+          dbus_connection_remove_filter (f->left_conn, shouted_signal_filter, f);
+          f->left_conn_shouted_signal_filter = FALSE;
+        }
+
       test_connection_shutdown (f->ctx, f->left_conn);
       dbus_connection_close (f->left_conn);
     }
@@ -2674,6 +2728,71 @@ static Config send_destination_prefix_config = {
     TEST_USER_ME, SPECIFY_ADDRESS
 };
 
+static void
+test_match_remove_fails (Fixture *f,
+                         gconstpointer context G_GNUC_UNUSED)
+{
+  const char *match_rule = "type='signal'";
+
+  if (f->skip)
+    return;
+
+  /* Unlike in test_match_remove_succeeds(), we never added this */
+  dbus_bus_remove_match (f->left_conn, match_rule, &f->e);
+  g_assert_cmpstr (f->e.name, ==, DBUS_ERROR_MATCH_RULE_NOT_FOUND);
+}
+
+static void
+test_match_remove_succeeds (Fixture *f,
+                            gconstpointer context G_GNUC_UNUSED)
+{
+  const char *match_rule = "type='signal'";
+
+  if (f->skip)
+    return;
+
+  add_shouted_signal_filter (f);
+
+  /* We use this to make sure that a method call from the "left" connection
+   * will get a reply from the "right", to sync up */
+  add_echo_filter (f);
+
+  /* Emit a signal from the "right" connection, and assert that the "left"
+   * does not receive it yet */
+  f->signal_counter = 0;
+  right_conn_emit_shouted (f);
+  /* Because messages are totally-ordered, if the "left" connection was
+   * going to receive the signal, it would receive it before it got
+   * the reply from this async call to the "right" connection */
+  echo_left_to_right (f, 1);
+  g_assert_cmpuint (f->signal_counter, ==, 0);
+
+  dbus_bus_add_match (f->left_conn, match_rule, &f->e);
+  test_assert_no_error (&f->e);
+
+  f->signal_counter = 0;
+
+  /* Emit a signal from the "right" connection, and assert that the "left"
+   * receives it */
+  right_conn_emit_shouted (f);
+
+  while (f->signal_counter < 1)
+    test_main_context_iterate (f->ctx, TRUE);
+
+  dbus_bus_remove_match (f->left_conn, match_rule, &f->e);
+  test_assert_no_error (&f->e);
+
+  /* Emit a signal from the "right" connection, and assert that the "left"
+   * does not receive it this time */
+  f->signal_counter = 0;
+  right_conn_emit_shouted (f);
+  /* Because messages are totally-ordered, if the "left" connection was
+   * going to receive the signal, it would receive it before it got
+   * the reply from this async call to the "right" connection */
+  echo_left_to_right (f, 1);
+  g_assert_cmpuint (f->signal_counter, ==, 0);
+}
+
 int
 main (int argc,
     char **argv)
@@ -2708,6 +2827,10 @@ main (int argc,
   g_test_add ("/limits/max-names-per-connection", Fixture,
       &max_names_per_connection_config,
       setup, test_max_names_per_connection, teardown);
+  g_test_add ("/match/remove/fails", Fixture, NULL,
+      setup, test_match_remove_fails, teardown);
+  g_test_add ("/match/remove/succeeds", Fixture, NULL,
+      setup, test_match_remove_succeeds, teardown);
   g_test_add ("/peer/ping", Fixture, NULL, setup, test_peer_ping, teardown);
   g_test_add ("/peer/get-machine-id", Fixture, NULL,
       setup, test_peer_get_machine_id, teardown);