Add a testcase for destroyObject

Validate that:
  -Dbus signal callbacks are established.
  -The propertyChangedTo filter works correctly.
  -The destroyObject action works correctly.

Change-Id: I0981fed76aa26ff275a401ae81fd230833dfc4cc
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/example/events.d/match2.yaml b/example/events.d/match2.yaml
index d31a694..84b28f1 100644
--- a/example/events.d/match2.yaml
+++ b/example/events.d/match2.yaml
@@ -4,25 +4,30 @@
 events:
     - name: Example Match(2)
       description: >
-          Matches any PropertiesChanged signal emitted
-          by /xyz/openbmc_project/testing.
+          Destroys the /deleteme1 and /deleteme2 objects
+          When the value of ExampleProperty2 on
+          /testing/inventory/trigger changes to xxxyyy.
       type: match
       signatures:
           - type: signal
-            path: /xyz/openbmc_project/Inventory/example
+            path: /testing/inventory/trigger1
             interface: org.freedesktop.DBus.Properties
             member: PropertiesChanged
       filters:
           - name: propertyChangedTo
             args:
-              interface: xyz.openbmc_project.Example.Iface1
-              property: ExampleProperty1
+              interface: xyz.openbmc_project.Example.Iface2
+              property: ExampleProperty2
               value:
                   type: string
-                  value: testString
+                  value: xxxyyy
       actions:
           - name: destroyObject
             args:
-                path: Example
+                path: /deleteme1
+          - name: destroyObject
+            args:
+                path: /deleteme2
+
 
 # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/test/test.cpp b/test/test.cpp
index 669879d..0a1fbd9 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -100,6 +100,25 @@
     return result.empty();
 }
 
+/**@brief Check an object for one or more interfaces. */
+template <typename ...T>
+auto hasInterfaces(const std::vector<std::string> &l, const Object<T...> &r)
+{
+    std::vector<std::string> stripped, interfaces;
+    std::transform(
+            r.cbegin(),
+            r.cend(),
+            std::back_inserter(stripped),
+            [](auto &p){ return p.first; });
+    std::set_difference(
+            stripped.cbegin(),
+            stripped.cend(),
+            l.cbegin(),
+            l.cend(),
+            std::back_inserter(interfaces));
+    return interfaces.empty();
+}
+
 void runTests(phosphor::inventory::manager::Manager &mgr)
 {
     const std::string root{ROOT};
@@ -112,6 +131,14 @@
                 INTERFACE,
                 "Notify");
     };
+    auto set = [&](const std::string &path)
+    {
+        return b.new_method_call(
+                SERVICE,
+                path.c_str(),
+                "org.freedesktop.DBus.Properties",
+                "Set");
+    };
 
     Object<std::string> obj{
         {
@@ -149,6 +176,91 @@
         assert(!moreSignals);
     }
 
+    // Make sure DBus signals are handled.
+    {
+        ObjectPath relDeleteMeOne{"/deleteme1"};
+        ObjectPath relDeleteMeTwo{"/deleteme2"};
+        ObjectPath relTriggerOne{"/trigger1"};
+        ObjectPath deleteMeOne{root + relDeleteMeOne};
+        ObjectPath deleteMeTwo{root + relDeleteMeTwo};
+        ObjectPath triggerOne{root + relTriggerOne};
+
+        // Create some objects to be deleted by an action.
+        {
+            auto m = notify();
+            m.append(relDeleteMeOne);
+            m.append(obj);
+            b.call(m);
+        }
+        {
+            auto m = notify();
+            m.append(relDeleteMeTwo);
+            m.append(obj);
+            b.call(m);
+        }
+
+        // Create the triggering object.
+        {
+            auto m = notify();
+            m.append(relTriggerOne);
+            m.append(obj);
+            b.call(m);
+        }
+
+        // Set a property that should not trigger due to a filter.
+        {
+            SignalQueue queue(
+                    "path='" + root + "',member='InterfacesRemoved'");
+            auto m = set(triggerOne);
+            m.append("xyz.openbmc_project.Example.Iface2");
+            m.append("ExampleProperty2");
+            m.append(sdbusplus::message::variant<std::string>("abc123"));
+            b.call(m);
+            auto sig{queue.pop()};
+            assert(!sig);
+        }
+
+        // Set a property that should trigger.
+        {
+            SignalQueue queue(
+                    "path='" + root + "',member='InterfacesRemoved'");
+
+            auto m = set(triggerOne);
+            m.append("xyz.openbmc_project.Example.Iface2");
+            m.append("ExampleProperty2");
+            m.append(sdbusplus::message::variant<std::string>("xxxyyy"));
+            b.call(m);
+
+            ObjectPath sigpath;
+            std::vector<std::string> interfaces;
+            {
+                std::vector<std::string> interfaces;
+                auto sig{queue.pop()};
+                assert(sig);
+                sig.read(sigpath);
+                assert(sigpath == deleteMeOne);
+                sig.read(interfaces);
+                std::sort(interfaces.begin(), interfaces.end());
+                assert(hasInterfaces(interfaces, obj));
+            }
+            {
+                std::vector<std::string> interfaces;
+                auto sig{queue.pop()};
+                assert(sig);
+                sig.read(sigpath);
+                assert(sigpath == deleteMeTwo);
+                sig.read(interfaces);
+                std::sort(interfaces.begin(), interfaces.end());
+                assert(hasInterfaces(interfaces, obj));
+            }
+            {
+                // Make sure there were only two signals.
+                auto sig{queue.pop()};
+                assert(!sig);
+            }
+        }
+    }
+
     mgr.shutdown();
     std::cout << "Success!" << std::endl;
 }