test suite failure - more detail ...

Olivier Andrieu oliv__a at users.sourceforge.net
Tue Apr 20 00:02:14 EST 2004


 Havoc Pennington [Sat, 17 Apr 2004]:
 > This still seems sensible to me. ServiceCreated/ServiceDeleted I think
 > can definitely be replaced by OwnerChanged, and OwnerChanged could
 > definitely be used by other apps to see when a new owner appears.
... 
 > I think it would be OK if rather than flags we had:
 >  service creation,   owner null -> new owner
 >  service deletion,   current owner -> owner null
 >  owner changed,      current owner -> new owner
 > 
 > i.e. you don't need the flags if you have both old and new owner in
 > the signal.
...
 > To sum up what feels right to me is:
 >  OwnerChanged (STRING service_name, STRING_OR_NIL old_owner,
 >                STRING_OR_NIL new_owner)
 >  ServiceAcquired/ServiceLost as-is.

OK, I implemented that. I wasn't too sure about the STRING_OR_NIL
overloading since I did not see this used anywhere else. 

A minor issue is that dbus_message_get_args isn't very helpful for
this kind of arguments : you have to check the signature or use a
DBusMessageIter to unpack the message elements. Perhaps
dbus_message_get_args could be modified so that is stores a NULL
pointer when the requested spec type is a DBUS_TYPE_STRING and the
corresponding message element is a DBUS_TYPE_NIL (instead of failing)?

The first patch implements ServiceOwnerChanged and removes
ServiceCreated and ServiceDeleted. The second one updates the tests
for this change.

Then I tried to implement the service tracking in DBusGProxyManager.
Here's what I'm doing: when a proxy for a 'real' service (ie not a
base service) is registered, the manager starts to 'track' this
service, i.e. listen to ServiceOwnerChanged signals concerning it and
record the base service that owns it. When the proxy is destroyed, the
tracking for the service stops.

It kind of works but it has some problems:

- When you create a proxy with dbus_gproxy_new_for_service() for a
service not known to the manager, it asks the bus about it with a
GetServiceOwner method. This introduces a round-trip to the bus that:
a) may fail and b) may not even be necessary if the service is not
supposed to send signals.
A solution would to add an argument in dbus_gproxy_new_for_service()
indicating wether we want this proxy to be able to receive signals,
but that feels like a kludge.

- The next problem is that it is not interacting nicely with service
activation. The test program in test/glib does this: send a
ActivateService message, receive the activation reply, then create a
proxy for the service. What happens is that the ServiceOwnerChanged
signal arrives before the proxy is created, so the service is not
tracked yet by the manager and the signal is ignored. Right after
that, the proxy is created and the client sends a GetServiceOwner
message, which is dumb because the bus just sent this information ! 

Any ideas on how to improve this ?

-- 
   Olivier
-------------- next part --------------
Index: doc/dbus-specification.xml
===================================================================
RCS file: /cvs/dbus/dbus/doc/dbus-specification.xml,v
retrieving revision 1.6
diff -u -r1.6 dbus-specification.xml
--- a/doc/dbus-specification.xml	15 Apr 2004 22:08:04 -0000	1.6
+++ b/doc/dbus-specification.xml	19 Apr 2004 11:29:04 -0000
@@ -2038,19 +2038,15 @@
         <para>
           This message is sent to a specific application when it loses primary
           ownership of a service.
-
-          [FIXME instead of ServiceLost/ServiceCreated going only to 
-          a specific app, why not just OwnerChanged that covers both 
-          lost and created and changed owner and deleted]
         </para>
       </sect3>
 
-      <sect3 id="bus-messages-service-created">
-        <title><literal>org.freedesktop.DBus.ServiceCreated</literal></title>
+      <sect3 id="bus-messages-service-owner-changed">
+        <title><literal>org.freedesktop.DBus.ServiceOwnerChanged</literal></title>
         <para>
-          As a method:
           <programlisting>
-            ServiceCreated (in STRING service_name)
+            ServiceOwnerChanged (STRING service_name, STRING_OR_NIL
+            old_owner, STRING_OR_NIL new_owner)
           </programlisting>
           Message arguments:
           <informaltable>
@@ -2070,46 +2066,15 @@
                 </row>
 	        <row>
 		  <entry>1</entry>
-		  <entry>UINT32</entry>
-		  <entry>Flags</entry>
+		  <entry>STRING or NIL</entry>
+		  <entry>Base service of previous owner, NIL if the
+		  service is newly created</entry>
 	        </row>
-              </tbody>
-            </tgroup>
-          </informaltable>
-        </para>
-        <para>
-          This message is broadcast to all applications when a service has been
-          successfully registered on the message bus.
-        </para>
-      </sect3>
-
-      <sect3 id="bus-messages-service-deleted">
-        <title><literal>org.freedesktop.DBus.ServiceDeleted</literal></title>
-        <para>
-          As a method:
-          <programlisting>
-            ServiceDeleted (in STRING service_name)
-          </programlisting>
-          Message arguments:
-          <informaltable>
-            <tgroup cols="3">
-              <thead>
-                <row>
-                  <entry>Argument</entry>
-                  <entry>Type</entry>
-                  <entry>Description</entry>
-                </row>
-              </thead>
-              <tbody>
-                <row>
-                  <entry>0</entry>
-                  <entry>STRING</entry>
-                  <entry>Name of the service</entry>
-                </row>
 	        <row>
-		  <entry>1</entry>
-		  <entry>UINT32</entry>
-		  <entry>Flags</entry>
+		  <entry>2</entry>
+		  <entry>STRING or NIL</entry>
+		  <entry>Base service of new owner, NIL if the
+		  service is no longer available</entry>
 	        </row>
               </tbody>
             </tgroup>
@@ -2117,7 +2082,8 @@
         </para>
         <para>
           This message is broadcast to all applications when a service has been
-          deleted from the message bus.
+          successfully registered on the message bus, has been deleted
+          or its primary owner has changed.
         </para>
       </sect3>
 
Index: bus/driver.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/driver.h,v
retrieving revision 1.7
diff -u -r1.7 driver.h
--- a/bus/driver.h	2 Dec 2003 10:44:21 -0000	1.7
+++ b/bus/driver.h	19 Apr 2004 11:29:04 -0000
@@ -32,9 +32,6 @@
                                               BusTransaction *transaction,
                                               DBusMessage    *message,
                                               DBusError      *error);
-dbus_bool_t bus_driver_send_service_deleted  (const char     *service_name,
-                                              BusTransaction *transaction,
-                                              DBusError      *error);
 dbus_bool_t bus_driver_send_service_lost     (DBusConnection *connection,
                                               const char     *service_name,
                                               BusTransaction *transaction,
@@ -43,8 +40,10 @@
                                               const char     *service_name,
                                               BusTransaction *transaction,
                                               DBusError      *error);
-dbus_bool_t bus_driver_send_service_created  (const char     *service_name,
-                                              BusTransaction *transaction,
-                                              DBusError      *error);
+dbus_bool_t bus_driver_send_service_owner_changed  (const char     *service_name,
+						    const char     *old_owner,
+						    const char     *new_owner,
+						    BusTransaction *transaction,
+						    DBusError      *error);
 
 #endif /* BUS_DRIVER_H */
Index: bus/driver.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/driver.c,v
retrieving revision 1.47
diff -u -r1.47 driver.c
--- a/bus/driver.c	15 Apr 2004 22:08:04 -0000	1.47
+++ b/bus/driver.c	19 Apr 2004 11:29:05 -0000
@@ -39,20 +39,24 @@
                                                     DBusError      *error);
 
 dbus_bool_t
-bus_driver_send_service_deleted (const char     *service_name,
-                                 BusTransaction *transaction,
-                                 DBusError      *error)
+bus_driver_send_service_owner_changed (const char     *service_name,
+				       const char     *old_owner,
+				       const char     *new_owner,
+				       BusTransaction *transaction,
+				       DBusError      *error)
 {
   DBusMessage *message;
+  DBusMessageIter iter;
   dbus_bool_t retval;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  _dbus_verbose ("sending service deleted: %s\n", service_name);
+  _dbus_verbose ("sending service owner changed: %s [%s -> %s]", 
+		 service_name, old_owner, new_owner);
 
   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                     "ServiceDeleted");
+                                     "ServiceOwnerChanged");
   
   if (message == NULL)
     {
@@ -60,62 +64,37 @@
       return FALSE;
     }
   
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) ||
-      !dbus_message_append_args (message,
-                                 DBUS_TYPE_STRING, service_name,
-                                 DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+    goto oom;
 
-  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
-  dbus_message_unref (message);
+  dbus_message_append_iter_init (message, &iter);
 
-  return retval;
-}
+  if (!dbus_message_iter_append_string (&iter, service_name))
+    goto oom;
 
-dbus_bool_t
-bus_driver_send_service_created (const char     *service_name,
-                                 BusTransaction *transaction,
-                                 DBusError      *error)
-{
-  DBusMessage *message;
-  dbus_bool_t retval;
+  if (old_owner != NULL)
+    retval = dbus_message_iter_append_string (&iter, old_owner);
+  else
+    retval = dbus_message_iter_append_nil (&iter);
+  if (!retval)
+    goto oom;
+
+  if (new_owner != NULL)
+    retval = dbus_message_iter_append_string (&iter, new_owner);
+  else
+    retval = dbus_message_iter_append_nil (&iter);
+  if (!retval)
+    goto oom;
 
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
-                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                     "ServiceCreated");
-  
-  if (message == NULL)
-    {
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
-  if (!dbus_message_append_args (message,
-                                 DBUS_TYPE_STRING, service_name,
-                                 DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
+
+ oom:
+  dbus_message_unref (message);
+  BUS_SET_OOM (error);
+  return FALSE;
 }
 
 dbus_bool_t
Index: bus/services.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/services.c,v
retrieving revision 1.20
diff -u -r1.20 services.c
--- a/bus/services.c	16 Mar 2004 18:00:34 -0000	1.20
+++ b/bus/services.c	19 Apr 2004 11:29:05 -0000
@@ -156,7 +156,10 @@
       return NULL;
     }
 
-  if (!bus_driver_send_service_created (service->name, transaction, error))
+  if (!bus_driver_send_service_owner_changed (service->name, 
+					      NULL,
+					      bus_connection_get_name (owner_if_created),
+					      transaction, error))
     {
       bus_service_unref (service);
       return NULL;
@@ -686,21 +689,32 @@
     }
   else if (_dbus_list_length_is_one (&service->owners))
     {
-      if (!bus_driver_send_service_deleted (service->name,
-                                            transaction, error))
+      if (!bus_driver_send_service_owner_changed (service->name,
+						  bus_connection_get_name (owner),
+						  NULL,
+						  transaction, error))
         return FALSE;
     }
   else
     {
       DBusList *link;
+      DBusConnection *new_owner;
       link = _dbus_list_get_first (&service->owners);
       _dbus_assert (link != NULL);
       link = _dbus_list_get_next_link (&service->owners, link);
 
       _dbus_assert (link != NULL);
 
+      new_owner = link->data;
+
+      if (!bus_driver_send_service_owner_changed (service->name,
+						  bus_connection_get_name (owner),
+						  bus_connection_get_name (new_owner),
+						  transaction, error))
+        return FALSE;
+
       /* This will be our new owner */
-      if (!bus_driver_send_service_acquired (link->data,
+      if (!bus_driver_send_service_acquired (new_owner,
                                              service->name,
                                              transaction,
                                              error))
-------------- next part --------------
Index: bus/dispatch.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.c,v
retrieving revision 1.57
diff -u -r1.57 dispatch.c
--- a/bus/dispatch.c	16 Mar 2004 18:00:34 -0000	1.57
+++ b/bus/dispatch.c	19 Apr 2004 11:26:09 -0000
@@ -474,68 +474,114 @@
 
 typedef struct
 {
+  enum { 
+    SERVICE_CREATED,
+    OWNER_CHANGED,
+    SERVICE_DELETED
+  } expected_kind;
   const char *expected_service_name;
   dbus_bool_t failed;
-} CheckServiceDeletedData;
+  DBusConnection *skip_connection;
+} CheckServiceOwnerChangedData;
 
 static dbus_bool_t
-check_service_deleted_foreach (DBusConnection *connection,
-                               void           *data)
+check_service_owner_changed_foreach (DBusConnection *connection,
+				     void           *data)
 {
-  CheckServiceDeletedData *d = data;
+  CheckServiceOwnerChangedData *d = data;
   DBusMessage *message;
   DBusError error;
-  char *service_name;
+  char *service_name, *old_owner, *new_owner;
+
+  if (d->expected_kind == SERVICE_CREATED 
+      && connection == d->skip_connection)
+    return TRUE;
 
   dbus_error_init (&error);
   d->failed = TRUE;
   service_name = NULL;
-  
+  old_owner = NULL;
+  new_owner = NULL;
+
   message = pop_message_waiting_for_memory (connection);
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
-                  connection, "ServiceDeleted");
+                  connection, "ServiceOwnerChanged");
       goto out;
     }
   else if (!dbus_message_is_signal (message,
                                     DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                    "ServiceDeleted"))
+                                    "ServiceOwnerChanged"))
     {
-      warn_unexpected (connection, message, "ServiceDeleted");
+      warn_unexpected (connection, message, "ServiceOwnerChanged");
 
       goto out;
     }
   else
     {
-      if (!dbus_message_get_args (message, &error,
-                                  DBUS_TYPE_STRING, &service_name,
-                                  DBUS_TYPE_INVALID))
-        {
-          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
-            {
-              _dbus_verbose ("no memory to get service name arg\n");
-            }
-          else
-            {
-              _dbus_assert (dbus_error_is_set (&error));
-              _dbus_warn ("Did not get the expected single string argument\n");
-              goto out;
-            }
-        }
-      else if (strcmp (service_name, d->expected_service_name) != 0)
-        {
-          _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
-                      d->expected_service_name,
-                      service_name);
-          goto out;
-        }
+      switch (d->expected_kind) 
+	{
+	case SERVICE_CREATED:
+	  dbus_message_get_args (message, &error,
+				 DBUS_TYPE_STRING, &service_name,
+				 DBUS_TYPE_NIL,
+				 DBUS_TYPE_STRING, &new_owner,
+				 DBUS_TYPE_INVALID);
+	  break;
+	case OWNER_CHANGED:
+	  dbus_message_get_args (message, &error,
+				 DBUS_TYPE_STRING, &service_name,
+				 DBUS_TYPE_STRING, &old_owner,
+				 DBUS_TYPE_STRING, &new_owner,
+				 DBUS_TYPE_INVALID);
+	  break;
+	case SERVICE_DELETED:
+	  dbus_message_get_args (message, &error,
+				 DBUS_TYPE_STRING, &service_name,
+				 DBUS_TYPE_STRING, &old_owner,
+				 DBUS_TYPE_NIL,
+				 DBUS_TYPE_INVALID);
+	  break;
+	}
+      if (dbus_error_is_set (&error))
+	{
+	  if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+	    {
+	      _dbus_verbose ("no memory to get service name arg\n");
+	    }
+	  else
+	    {
+	      _dbus_warn ("Did not get the expected arguments\n");
+	      goto out;
+	    }
+	}
+      else 
+	{
+	  if (strcmp (service_name, d->expected_service_name) != 0)
+	    {
+	      _dbus_warn ("expected info on service %s, got info on %s\n",
+			  d->expected_service_name,
+			  service_name);
+	      goto out;
+	    }
+
+	  if (*service_name == ':' && new_owner
+	      && strcmp (service_name, new_owner) != 0)
+	    {
+	      _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n",
+			  service_name, old_owner, new_owner);
+	      goto out;
+	    }
+	}
     }
 
   d->failed = FALSE;
   
  out:
   dbus_free (service_name);
+  dbus_free (old_owner);
+  dbus_free (new_owner);
   dbus_error_free (&error);
   
   if (message)
@@ -544,13 +590,14 @@
   return !d->failed;
 }
 
+
 static void
 kill_client_connection (BusContext     *context,
                         DBusConnection *connection)
 {
   char *base_service;
   const char *s;
-  CheckServiceDeletedData csdd;
+  CheckServiceOwnerChangedData socd;
 
   _dbus_verbose ("killing connection %p\n", connection);
   
@@ -578,16 +625,18 @@
   connection = NULL;
   _dbus_assert (!bus_test_client_listed (connection));
   
-  csdd.expected_service_name = base_service;
-  csdd.failed = FALSE;
-
-  bus_test_clients_foreach (check_service_deleted_foreach,
-                            &csdd);
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = base_service;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);
 
   dbus_free (base_service);
   
-  if (csdd.failed)
-    _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
+  if (socd.failed)
+    _dbus_assert_not_reached ("didn't get the expected ServiceOwnerChanged (deletion) messages");
   
   if (!check_no_leftovers (context))
     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
@@ -636,81 +685,6 @@
   return !d->failed;
 }
 
-typedef struct
-{
-  DBusConnection *skip_connection;
-  const char *expected_service_name;
-  dbus_bool_t failed;
-} CheckServiceCreatedData;
-
-static dbus_bool_t
-check_service_created_foreach (DBusConnection *connection,
-                               void           *data)
-{
-  CheckServiceCreatedData *d = data;
-  DBusMessage *message;
-  DBusError error;
-  char *service_name;
-
-  if (connection == d->skip_connection)
-    return TRUE;
-
-  dbus_error_init (&error);
-  d->failed = TRUE;
-  service_name = NULL;
-  
-  message = pop_message_waiting_for_memory (connection);
-  if (message == NULL)
-    {
-      _dbus_warn ("Did not receive a message on %p, expecting %s\n",
-                  connection, "ServiceCreated");
-      goto out;
-    }
-  else if (!dbus_message_is_signal (message,
-                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                    "ServiceCreated"))
-    {
-      warn_unexpected (connection, message, "ServiceCreated");
-      goto out;
-    }
-  else
-    {
-      if (!dbus_message_get_args (message, &error,
-                                  DBUS_TYPE_STRING, &service_name,
-                                  DBUS_TYPE_INVALID))
-        {
-          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
-            {
-              _dbus_verbose ("no memory to get service name arg\n");
-            }
-          else
-            {
-              _dbus_assert (dbus_error_is_set (&error));
-              _dbus_warn ("Did not get the expected single string argument\n");
-              goto out;
-            }
-        }
-      else if (strcmp (service_name, d->expected_service_name) != 0)
-        {
-          _dbus_warn ("expected creation of service %s, got creation of %s\n",
-                      d->expected_service_name,
-                      service_name);
-          goto out;
-        }
-    }
-
-  d->failed = FALSE;
-  
- out:
-  dbus_free (service_name);
-  dbus_error_free (&error);
-  
-  if (message)
-    dbus_message_unref (message);
-
-  return !d->failed;
-}
-
 static dbus_bool_t
 check_no_leftovers (BusContext *context)
 {
@@ -816,7 +790,7 @@
     }
   else
     {
-      CheckServiceCreatedData scd;
+      CheckServiceOwnerChangedData socd;
       
       if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
         {
@@ -854,13 +828,14 @@
       while (!dbus_bus_set_base_service (connection, name))
         _dbus_wait_for_memory ();
       
-      scd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
-      scd.failed = FALSE;
-      scd.expected_service_name = name;
-      bus_test_clients_foreach (check_service_created_foreach,
-                                &scd);
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = name;
+      socd.failed = FALSE;
+      socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
       
-      if (scd.failed)
+      if (socd.failed)
         goto out;
       
       /* Client should also have gotten ServiceAcquired */
@@ -872,6 +847,13 @@
                       "ServiceAcquired");
           goto out;
         }
+      if (! dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+				    "ServiceAcquired"))
+        {
+          _dbus_warn ("Expecting %s, got smthg else\n",
+                      "ServiceAcquired");
+          goto out;
+        }
       
     retry_get_acquired_name:
       if (!dbus_message_get_args (message, &error,
@@ -1100,9 +1082,6 @@
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
-  
-  dbus_error_init (&error);
   
   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
@@ -1204,10 +1183,7 @@
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
     
-  dbus_error_init (&error);
-
   message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
                                           "/org/freedesktop/TestSuite",
                                           "org.freedesktop.TestSuite",
@@ -1301,9 +1277,10 @@
   DBusMessage *message;
   dbus_bool_t retval;
   DBusError error;
-  char *base_service;
+  char *base_service, *base_service_from_bus;
   
   base_service = NULL;
+  base_service_from_bus = NULL;
   retval = FALSE;
   
   dbus_error_init (&error);
@@ -1313,54 +1290,61 @@
 
   if (dbus_message_is_signal (message,
                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                              "ServiceCreated"))
+                              "ServiceOwnerChanged"))
     {
-      char *service_name;
-      CheckServiceCreatedData scd;
+      CheckServiceOwnerChangedData socd;
 
     reget_service_name_arg:
       if (!dbus_message_get_args (message, &error,
-                                  DBUS_TYPE_STRING, &service_name,
+                                  DBUS_TYPE_STRING, &base_service,
+				  DBUS_TYPE_NIL,
+                                  DBUS_TYPE_STRING, &base_service_from_bus,
                                   DBUS_TYPE_INVALID))
         {
           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
             {
               dbus_error_free (&error);
+	      dbus_free (base_service);
+	      dbus_free (base_service_from_bus);
               _dbus_wait_for_memory ();
               goto reget_service_name_arg;
             }
           else
             {
               _dbus_warn ("Message %s doesn't have a service name: %s\n",
-                          "ServiceCreated",
+                          "ServiceOwnerChanged (creation)",
                           error.message);
-              dbus_error_free (&error);
               goto out;
             }
         }
 
-      if (*service_name != ':')
+      if (*base_service != ':')
         {
           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
-                      service_name);
+                      base_service);
           goto out;
         }
-              
-      base_service = service_name;
-      service_name = NULL;
-      
-      scd.skip_connection = connection;
-      scd.failed = FALSE;
-      scd.expected_service_name = base_service;
-      bus_test_clients_foreach (check_service_created_foreach,
-                                &scd);
+         
+      if (strcmp (base_service, base_service_from_bus) != 0)
+	{
+          _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n",
+                      base_service, base_service_from_bus);
+          goto out;
+        }
+     
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = base_service;
+      socd.failed = FALSE;
+      socd.skip_connection = connection;
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
       
-      if (scd.failed)
+      if (socd.failed)
         goto out;
     }
   else
     {
-      warn_unexpected (connection, message, "ServiceCreated for base service");
+      warn_unexpected (connection, message, "ServiceOwnerChanged (creation) for base service");
 
       goto out;
     }
@@ -1376,10 +1360,10 @@
  out:
   if (message)
     dbus_message_unref (message);
+  dbus_free (base_service);
+  dbus_free (base_service_from_bus);
+  dbus_error_free (&error);
 
-  if (base_service)
-    dbus_free (base_service);
-  
   return retval;
 }
 
@@ -1404,28 +1388,38 @@
 
   if (dbus_message_is_signal (message,
                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                              "ServiceCreated"))
+                              "ServiceOwnerChanged"))
     {
-      char *service_name;
-      CheckServiceCreatedData scd;
+      char *service_name, *base_service_from_bus;
+
+      CheckServiceOwnerChangedData socd;
+
+      service_name = NULL;
+      base_service_from_bus = NULL;
 
     reget_service_name_arg:
       if (!dbus_message_get_args (message, &error,
                                   DBUS_TYPE_STRING, &service_name,
+				  DBUS_TYPE_NIL,
+                                  DBUS_TYPE_STRING, &base_service_from_bus,
                                   DBUS_TYPE_INVALID))
         {
           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
             {
               dbus_error_free (&error);
+	      dbus_free (service_name);
+	      dbus_free (base_service_from_bus);
               _dbus_wait_for_memory ();
               goto reget_service_name_arg;
             }
           else
             {
               _dbus_warn ("Message %s doesn't have a service name: %s\n",
-                          "ServiceCreated",
+                          "ServiceOwnerChanged (creation)",
                           error.message);
               dbus_error_free (&error);
+	      dbus_free (service_name);
+	      dbus_free (base_service_from_bus);
               goto out;
             }
         }
@@ -1435,18 +1429,30 @@
           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
                       activated_name, service_name);
           dbus_free (service_name);
+	  dbus_free (base_service_from_bus);
+          goto out;
+        }
+
+      if (strcmp (base_service_name, base_service_from_bus) != 0)
+        {
+          _dbus_warn ("GetServiceOwner reports wrong base service: %s owner, expected %s instead\n",
+                      base_service_from_bus, base_service_name);
+          dbus_free (service_name);
+	  dbus_free (base_service_from_bus);
           goto out;
         }
       
-      scd.skip_connection = connection;
-      scd.failed = FALSE;
-      scd.expected_service_name = service_name;
-      bus_test_clients_foreach (check_service_created_foreach,
-                                &scd);
+      socd.expected_kind = SERVICE_CREATED;
+      socd.skip_connection = connection;
+      socd.failed = FALSE;
+      socd.expected_service_name = service_name;
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
           
       dbus_free (service_name);
+      dbus_free (base_service_from_bus);
 
-      if (scd.failed)
+      if (socd.failed)
         goto out;
           
       dbus_message_unref (message);
@@ -1460,7 +1466,7 @@
     }
   else
     {
-      warn_unexpected (connection, message, "ServiceCreated for the activated name");
+      warn_unexpected (connection, message, "ServiceOwnerChanged for the activated name");
       
       goto out;
     }
@@ -1539,10 +1545,10 @@
 
   if (dbus_message_is_signal (message,
                               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                              "ServiceCreated"))
+                              "ServiceOwnerChanged"))
     {
       char *service_name;
-      CheckServiceCreatedData scd;
+      CheckServiceOwnerChangedData socd;
       
     reget_service_name_arg:
       if (!dbus_message_get_args (message, &error,
@@ -1573,15 +1579,16 @@
           goto out;
         }
       
-      scd.skip_connection = connection;
-      scd.failed = FALSE;
-      scd.expected_service_name = service_name;
-      bus_test_clients_foreach (check_service_created_foreach,
-				&scd);
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = service_name;
+      socd.failed = FALSE;
+      socd.skip_connection = connection; 
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+				&socd);
       
       dbus_free (service_name);
       
-      if (scd.failed)
+      if (socd.failed)
         goto out;
       
       /* Note that this differs from regular activation in that we don't get a
@@ -1593,7 +1600,7 @@
     }
   else
     {
-      warn_unexpected (connection, message, "ServiceCreated for the activated name");
+      warn_unexpected (connection, message, "ServiceOwnerChanged (creation) for the activated name");
       
       goto out;
     }
@@ -1615,32 +1622,33 @@
 {
   DBusMessage *message;
   dbus_bool_t retval;
-  DBusError error;
-  CheckServiceDeletedData csdd;
+  CheckServiceOwnerChangedData socd;
 
   message = NULL;
   retval = FALSE;
   
-  dbus_error_init (&error);
-
-  /* Now we are expecting ServiceDeleted messages for the base
+  /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base
    * service and the activated_name.  The base service
    * notification is required to come last.
    */
-  csdd.expected_service_name = activated_name;
-  csdd.failed = FALSE;
-  bus_test_clients_foreach (check_service_deleted_foreach,
-                            &csdd);      
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = activated_name;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);      
 
-  if (csdd.failed)
+  if (socd.failed)
     goto out;
       
-  csdd.expected_service_name = base_service;
-  csdd.failed = FALSE;
-  bus_test_clients_foreach (check_service_deleted_foreach,
-                            &csdd);
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = base_service;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);
 
-  if (csdd.failed)
+  if (socd.failed)
     goto out;
 
   retval = TRUE;
@@ -1875,13 +1883,10 @@
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
   char *base_service;
 
   base_service = NULL;
   
-  dbus_error_init (&error);
-  
   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
@@ -1965,8 +1970,11 @@
     }
   else
     {
-      dbus_bool_t got_service_deleted;
-      dbus_bool_t got_error;
+      enum { 
+	GOT_SERVICE_CREATED,
+	GOT_SERVICE_DELETED,
+	GOT_ERROR,
+	GOT_SMTHG_ELSE } message_kind;
       
       if (!check_base_service_activated (context, connection,
                                          message, &base_service))
@@ -1985,65 +1993,92 @@
           goto out;
         }
 
-      got_service_deleted = dbus_message_is_signal (message,
-                                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                                    "ServiceDeleted");
-      got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
+      if (dbus_message_is_signal (message,
+				  DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+				  "ServiceOwnerChanged"))
+	{
+	  const char *signature = dbus_message_get_signature (message);
+	  if (strcmp (signature, "svs") == 0)
+	    message_kind = GOT_SERVICE_CREATED;
+	  else if (strcmp (signature, "ssv") == 0)
+	    message_kind = GOT_SERVICE_DELETED;
+	  else
+	    {
+	      _dbus_warn ("Received a ServiceOwnerChanged message, but neither a creation or deletion one\n");
+	      message_kind = GOT_SMTHG_ELSE;
+	    }
+	}
+      else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+	message_kind = GOT_ERROR;
+      else
+	{
+	  _dbus_warn ("Unexpected message after ActivateService "
+		      "(should be an error or a service announcement");
+	  message_kind = GOT_SMTHG_ELSE;
+	}
       
       dbus_connection_return_message (connection, message);
       message = NULL;
 
-      if (got_error)
-        {
+      switch (message_kind)
+	{
+	case GOT_SMTHG_ELSE:
+	  goto out;
+
+	case GOT_ERROR:
           if (!check_got_error (context, connection,
                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
                                 DBUS_ERROR_NO_MEMORY,
                                 NULL))
             goto out;
-
           /* A service deleted should be coming along now after this error.
            * We can also get the error *after* the service deleted.
            */
-          got_service_deleted = TRUE;
-        }
-      
-      if (got_service_deleted)
-        {
-          /* The service started up and got a base address, but then
-           * failed to register under EXISTENT_SERVICE_NAME
-           */
-          CheckServiceDeletedData csdd;
-          
-          csdd.expected_service_name = base_service;
-          csdd.failed = FALSE;
-          bus_test_clients_foreach (check_service_deleted_foreach,
-                                    &csdd);
 
-          if (csdd.failed)
-            goto out;
+	  /* fall through */
 
-          /* Now we should get an error about the service exiting
-           * if we didn't get it before.
-           */
-          if (!got_error)
-            {
-              block_connection_until_message_from_bus (context, connection);
+	case GOT_SERVICE_DELETED:
+	  {
+	    /* The service started up and got a base address, but then
+	     * failed to register under EXISTENT_SERVICE_NAME
+	     */
+	    CheckServiceOwnerChangedData socd;
+
+	    socd.expected_kind = SERVICE_DELETED;
+	    socd.expected_service_name = base_service;
+	    socd.failed = FALSE;
+	    socd.skip_connection = NULL;
+	    
+	    bus_test_clients_foreach (check_service_owner_changed_foreach,
+				      &socd);
+
+	    if (socd.failed)
+	      goto out;
+
+	    /* Now we should get an error about the service exiting
+	     * if we didn't get it before.
+	     */
+	    if (message_kind != GOT_ERROR)
+	      {
+		block_connection_until_message_from_bus (context, connection);
               
-              /* and process everything again */
-              bus_test_run_everything (context);
+		/* and process everything again */
+		bus_test_run_everything (context);
               
-              if (!check_got_error (context, connection,
-                                    DBUS_ERROR_SPAWN_CHILD_EXITED,
-                                    NULL))
-                goto out;
-            }
-        }
-      else
-        {
+		if (!check_got_error (context, connection,
+				      DBUS_ERROR_SPAWN_CHILD_EXITED,
+				      NULL))
+		  goto out;
+	      }
+	    break;
+	  }
+
+	case GOT_SERVICE_CREATED:
           message = pop_message_waiting_for_memory (connection);
           if (message == NULL)
             {
-              _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
+              _dbus_warn ("Failed to pop message we just put back! "
+			  "should have been a ServiceOwnerChanged (creation)\n");
               goto out;
             }
           
@@ -2054,7 +2089,6 @@
           dbus_message_unref (message);
           message = NULL;
 
-
           if (!check_no_leftovers (context))
             {
               _dbus_warn ("Messages were left over after successful activation\n");
@@ -2064,9 +2098,11 @@
           if (!check_send_exit_to_service (context, connection,
                                            EXISTENT_SERVICE_NAME, base_service))
             goto out;
-        }
+
+	  break;
+	}
     }
-  
+
   retval = TRUE;
   
  out:
@@ -2089,9 +2125,6 @@
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
-  
-  dbus_error_init (&error);
   
   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
@@ -2195,11 +2228,6 @@
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
-
-  dbus_error_init (&error);
-
-  dbus_error_init (&error);
 
   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
                                           "/org/freedesktop/TestSuite",
@@ -2296,13 +2324,10 @@
   DBusMessage *message;
   dbus_uint32_t serial;
   dbus_bool_t retval;
-  DBusError error;
   char *base_service;
 
   base_service = NULL;
 
-  dbus_error_init (&error);
-
   message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
                                           "/org/freedesktop/TestSuite",
                                           "org.freedesktop.TestSuite",
@@ -2346,7 +2371,7 @@
 
   retval = FALSE;
   
-  /* Should get ServiceCreated for the base service, or an error. */
+  /* Should get ServiceOwnerChanged (creation) for the base service, or an error. */
   message = pop_message_waiting_for_memory (connection);
   if (message == NULL)
     {
@@ -2385,8 +2410,11 @@
     }
   else
     {
-      dbus_bool_t got_service_deleted;
-      dbus_bool_t got_error;
+      enum { 
+	GOT_SERVICE_CREATED,
+	GOT_SERVICE_DELETED,
+	GOT_ERROR,
+	GOT_SMTHG_ELSE } message_kind;
       
       if (!check_base_service_activated (context, connection,
                                          message, &base_service))
@@ -2408,16 +2436,39 @@
           goto out;
         }
 
-      got_service_deleted = dbus_message_is_signal (message,
-                                                    DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
-                                                    "ServiceDeleted");
-      got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
+      if (dbus_message_is_signal (message,
+				  DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+				  "ServiceOwnerChanged"))
+	{
+	  const char *signature = dbus_message_get_signature (message);
+	  if (strcmp (signature, "svs") == 0)
+	    message_kind = GOT_SERVICE_CREATED;
+	  else if (strcmp (signature, "ssv") == 0)
+	    message_kind = GOT_SERVICE_DELETED;
+	  else
+	    {
+	      _dbus_warn ("Received a ServiceOwnerChanged message, but neither a creation or deletion one\n");
+	      message_kind = GOT_SMTHG_ELSE;
+	    }
+	}
+      else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+	message_kind = GOT_ERROR;
+      else
+	{
+	  _dbus_warn ("Unexpected message after auto activation "
+		      "(should be an error or a service announcement");
+	  message_kind = GOT_SMTHG_ELSE;
+	}
 
       dbus_connection_return_message (connection, message);
       message = NULL;
 
-      if (got_error)
-        {
+      switch (message_kind)
+	{
+	case GOT_SMTHG_ELSE:
+	  goto out;
+
+	case GOT_ERROR:
           if (!check_got_error (context, connection,
                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
                                 DBUS_ERROR_NO_MEMORY,
@@ -2427,28 +2478,30 @@
           /* A service deleted should be coming along now after this error.
            * We can also get the error *after* the service deleted.
            */
-          got_service_deleted = TRUE;
-        }
-      
-      if (got_service_deleted)
-        {
-          /* The service started up and got a base address, but then
-           * failed to register under EXISTENT_SERVICE_NAME
-           */
-          CheckServiceDeletedData csdd;
+
+	  /* fall through */
+
+	case GOT_SERVICE_DELETED:
+	  {
+	    /* The service started up and got a base address, but then
+	     * failed to register under EXISTENT_SERVICE_NAME
+	     */
+	    CheckServiceOwnerChangedData socd;
           
-          csdd.expected_service_name = base_service;
-          csdd.failed = FALSE;
-          bus_test_clients_foreach (check_service_deleted_foreach,
-                                    &csdd);
+	    socd.expected_kind = SERVICE_DELETED;
+	    socd.expected_service_name = base_service;
+	    socd.failed = FALSE;
+	    socd.skip_connection = NULL;
+	    bus_test_clients_foreach (check_service_owner_changed_foreach,
+				      &socd);
 
-          if (csdd.failed)
+          if (socd.failed)
             goto out;
 	  
           /* Now we should get an error about the service exiting
            * if we didn't get it before.
            */
-          if (!got_error)
+          if (message_kind != GOT_ERROR)
             {
               block_connection_until_message_from_bus (context, connection);
               
@@ -2460,25 +2513,32 @@
                                     NULL))
                 goto out;
             }
-        }
-      else
-        {
+
+	  break;
+	  }
+
+	case GOT_SERVICE_CREATED:
 	  message = pop_message_waiting_for_memory (connection);
 	  if (message == NULL)
             {
-              _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
+              _dbus_warn ("Failed to pop message we just put back! "
+			  "should have been a ServiceOwnerChanged (creation)\n");
               goto out;
             }
 
-	  /* Check that ServiceCreated was correctly received */
+	  /* Check that ServiceOwnerChanged (creation) was correctly received */
           if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
 					     base_service, message))
             goto out;
 
           dbus_message_unref (message);
           message = NULL;
+
+	  break;
 	}
 
+      /* WEIRD */
+
       /* Note: if this test is run in OOM mode, it will block when the bus
        * doesn't send a reply due to OOM.
        */
@@ -2675,7 +2735,6 @@
   
   check2_try_iterations (context, foo, "segfault_service_auto_activation",
 			 check_segfault_service_auto_activation);
-
 #if 0
   /* Note: need to resolve some issues with the testing code in order to run
    * this in oom (handle that we sometimes don't get replies back from the bus
Index: test/test-service.c
===================================================================
RCS file: /cvs/dbus/dbus/test/test-service.c,v
retrieving revision 1.15
diff -u -r1.15 test-service.c
--- a/test/test-service.c	21 Mar 2004 16:26:56 -0000	1.15
+++ b/test/test-service.c	19 Apr 2004 11:26:09 -0000
@@ -195,7 +195,7 @@
                                      0, &error);
   if (dbus_error_is_set (&error))
     {
-      fprintf (stderr, "Error %s", error.message);
+      fprintf (stderr, "Error %s\n", error.message);
       _dbus_verbose ("*** Failed to acquire service: %s\n",
                      error.message);
       dbus_error_free (&error);


More information about the dbus mailing list