test: Move trigger objects to dedicated thread

Put the trigger object in its own thread rather than
the inventory manager thread.  This allows the thread
under test to make calls to it.

Change-Id: I181d2d46a10e4193653df61205ac3380a1d4db2e
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/example/events.d/match1.yaml b/example/events.d/match1.yaml
index d419c74..2219c9f 100644
--- a/example/events.d/match1.yaml
+++ b/example/events.d/match1.yaml
@@ -6,12 +6,12 @@
       description: >
           Sets the value of ExampleProperty1 on /changeme
           when the value of ExampleProperty2 on
-          /testing/inventory/trigger2 changes to yyyxxx.
+          /testing/trigger2 changes to yyyxxx.
       type: match
       signatures:
           - type: signal
             interface: org.freedesktop.DBus.Properties
-            path: /testing/inventory/trigger2
+            path: /testing/trigger2
             member: PropertiesChanged
       filters:
           - name: propertyChangedTo
diff --git a/example/events.d/match2.yaml b/example/events.d/match2.yaml
index d59e4da..22f7c80 100644
--- a/example/events.d/match2.yaml
+++ b/example/events.d/match2.yaml
@@ -6,11 +6,11 @@
       description: >
           Destroys the /deleteme1 and /deleteme2 objects
           When the value of ExampleProperty2 on
-          /testing/inventory/trigger changes to xxxyyy.
+          /testing/trigger1 changes to xxxyyy.
       type: match
       signatures:
           - type: signal
-            path: /testing/inventory/trigger1
+            path: /testing/trigger1
             interface: org.freedesktop.DBus.Properties
             member: PropertiesChanged
       filters:
diff --git a/test/test.cpp b/test/test.cpp
index 28fa611..621860a 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -19,10 +19,59 @@
 #include <iostream>
 #include <algorithm>
 #include <thread>
+#include <chrono>
+#include <xyz/openbmc_project/Example/Iface1/server.hpp>
+#include <xyz/openbmc_project/Example/Iface2/server.hpp>
 
-constexpr auto SERVICE = "phosphor.inventory.test";
-constexpr auto INTERFACE = IFACE;
-constexpr auto ROOT = "/testing/inventory";
+using namespace std::literals::chrono_literals;
+using namespace std::literals::string_literals;
+
+constexpr auto MGR_SERVICE = "phosphor.inventory.test.mgr";
+constexpr auto MGR_INTERFACE = IFACE;
+constexpr auto MGR_ROOT = "/testing/inventory";
+constexpr auto EXAMPLE_SERVICE = "phosphor.inventory.test.example";
+constexpr auto EXAMPLE_ROOT = "/testing";
+
+const auto trigger1 = sdbusplus::message::object_path(EXAMPLE_ROOT +
+                      "/trigger1"s);
+const auto trigger2 = sdbusplus::message::object_path(EXAMPLE_ROOT +
+                      "/trigger2"s);
+
+using ExampleIface1 = sdbusplus::xyz::openbmc_project::Example::server::Iface1;
+using ExampleIface2 = sdbusplus::xyz::openbmc_project::Example::server::Iface2;
+
+/** @class ExampleService
+ *  @brief Host an object for triggering events.
+ */
+struct ExampleService
+{
+    ~ExampleService() = default;
+    ExampleService() :
+        shutdown(false),
+        bus(sdbusplus::bus::new_default()),
+        objmgr(sdbusplus::server::manager::manager(bus, MGR_ROOT))
+    {
+        bus.request_name(EXAMPLE_SERVICE);
+    }
+
+    void run()
+    {
+        sdbusplus::server::object::object <
+        ExampleIface1, ExampleIface2 > t1(bus, trigger1.str.c_str());
+        sdbusplus::server::object::object <
+        ExampleIface1, ExampleIface2 > t2(bus, trigger2.str.c_str());
+
+        while (!shutdown)
+        {
+            bus.process_discard();
+            bus.wait((5000000us).count());
+        }
+    }
+
+    volatile bool shutdown;
+    sdbusplus::bus::bus bus;
+    sdbusplus::server::manager::manager objmgr;
+};
 
 /** @class SignalQueue
  *  @brief Store DBus signals in a queue.
@@ -112,22 +161,24 @@
     return interfaces.empty();
 }
 
-void runTests(phosphor::inventory::manager::Manager& mgr)
+void runTests()
 {
-    const std::string root{ROOT};
+    const std::string root{MGR_ROOT};
+    const std::string exampleRoot{EXAMPLE_ROOT};
     auto b = sdbusplus::bus::new_default();
+
     auto notify = [&]()
     {
         return b.new_method_call(
-                   SERVICE,
-                   ROOT,
-                   INTERFACE,
+                   MGR_SERVICE,
+                   MGR_ROOT,
+                   MGR_INTERFACE,
                    "Notify");
     };
     auto set = [&](const std::string & path)
     {
         return b.new_method_call(
-                   SERVICE,
+                   EXAMPLE_SERVICE,
                    path.c_str(),
                    "org.freedesktop.DBus.Properties",
                    "Set");
@@ -174,10 +225,8 @@
     {
         sdbusplus::message::object_path relDeleteMeOne{"/deleteme1"};
         sdbusplus::message::object_path relDeleteMeTwo{"/deleteme2"};
-        sdbusplus::message::object_path relTriggerOne{"/trigger1"};
         std::string deleteMeOne{root + relDeleteMeOne.str};
         std::string deleteMeTwo{root + relDeleteMeTwo.str};
-        std::string triggerOne{root + relTriggerOne.str};
 
         // Create some objects to be deleted by an action.
         {
@@ -193,19 +242,11 @@
             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);
+            auto m = set(trigger1.str);
             m.append("xyz.openbmc_project.Example.Iface2");
             m.append("ExampleProperty2");
             m.append(sdbusplus::message::variant<std::string>("abc123"));
@@ -219,7 +260,7 @@
             SignalQueue queue(
                 "path='" + root + "',member='InterfacesRemoved'");
 
-            auto m = set(triggerOne);
+            auto m = set(trigger1.str);
             m.append("xyz.openbmc_project.Example.Iface2");
             m.append("ExampleProperty2");
             m.append(sdbusplus::message::variant<std::string>("xxxyyy"));
@@ -258,9 +299,7 @@
     // Validate the set property action.
     {
         sdbusplus::message::object_path relChangeMe{"/changeme"};
-        sdbusplus::message::object_path relTriggerTwo{"/trigger2"};
         std::string changeMe{root + relChangeMe.str};
-        std::string triggerTwo{root + relTriggerTwo.str};
 
         // Create an object to be updated by the set property action.
         {
@@ -270,19 +309,11 @@
             b.call(m);
         }
 
-        // Create the triggering object.
-        {
-            auto m = notify();
-            m.append(relTriggerTwo);
-            m.append(obj);
-            b.call(m);
-        }
-
         // Trigger and validate the change.
         {
             SignalQueue queue(
                 "path='" + changeMe + "',member='PropertiesChanged'");
-            auto m = set(triggerTwo);
+            auto m = set(trigger2.str);
             m.append("xyz.openbmc_project.Example.Iface2");
             m.append("ExampleProperty2");
             m.append(sdbusplus::message::variant<std::string>("yyyxxx"));
@@ -302,26 +333,36 @@
             }
         }
     }
-
-    mgr.shutdown();
-    std::cout << "Success!" << std::endl;
 }
 
 int main()
 {
     phosphor::inventory::manager::Manager mgr(
         sdbusplus::bus::new_default(),
-        SERVICE, ROOT, INTERFACE);
+        MGR_SERVICE, MGR_ROOT, MGR_INTERFACE);
+    ExampleService d;
 
-    auto f = [](auto mgr)
+    auto f1 = [](auto mgr)
     {
         mgr->run();
     };
-    auto t = std::thread(f, &mgr);
-    runTests(mgr);
+    auto f2 = [](auto d)
+    {
+        d->run();
+    };
 
-    // Wait for server thread to exit.
-    t.join();
+    auto t1 = std::thread(f1, &mgr);
+    auto t2 = std::thread(f2, &d);
+
+    runTests();
+
+    mgr.shutdown();
+    d.shutdown = true;
+
+    // Wait for server threads to exit.
+    t1.join();
+    t2.join();
+    std::cout << "Success!  Waiting for threads to exit..." << std::endl;
 
     return 0;
 }