diff options
| author | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2016-11-30 22:02:28 -0500 |
|---|---|---|
| committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2016-12-15 10:44:06 -0500 |
| commit | abb2a1aba4cf209e7e94e4ea8596b6150e3a3492 (patch) | |
| tree | 835ffab33b5396de8ede92d2d25e6faefec07420 /test | |
| parent | 65ffffa9c115d51a0b184f627e8706cdd47f8b16 (diff) | |
| download | phosphor-inventory-manager-abb2a1aba4cf209e7e94e4ea8596b6150e3a3492.tar.gz phosphor-inventory-manager-abb2a1aba4cf209e7e94e4ea8596b6150e3a3492.zip | |
Enhance notify testcase
Validate signal content rather than doing explicit property
lookups. This avoids race conditions and additionally validates
that a signal is sent with the correct values.
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Change-Id: Iaf13b1dfd68eeaf8ab7e8dc3bf045f824c3c803a
Diffstat (limited to 'test')
| -rw-r--r-- | test/test.cpp | 132 |
1 files changed, 115 insertions, 17 deletions
diff --git a/test/test.cpp b/test/test.cpp index f089fcd..669879d 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -16,6 +16,8 @@ #include "../manager.hpp" #include "../config.h" #include <cassert> +#include <iostream> +#include <algorithm> constexpr auto SERVICE = "phosphor.inventory.test"; constexpr auto INTERFACE = IFACE; @@ -30,46 +32,142 @@ auto server_thread(void *data) return static_cast<void *>(nullptr); } -void runTests(phosphor::inventory::manager::Manager &mgr) +/** @class SignalQueue + * @brief Store DBus signals in a queue. + */ +class SignalQueue { - auto b = sdbusplus::bus::new_default(); + public: + ~SignalQueue() = default; + SignalQueue() = delete; + SignalQueue(const SignalQueue &) = delete; + SignalQueue(SignalQueue &&) = default; + SignalQueue& operator=(const SignalQueue &) = delete; + SignalQueue& operator=(SignalQueue &&) = default; + explicit SignalQueue(const std::string &match) : + _bus(sdbusplus::bus::new_default()), + _match(_bus, match.c_str(), &callback, this), + _next(nullptr) + { + } - // make sure the notify method works + auto &&pop(unsigned timeout=1000000) { - auto m = b.new_method_call(SERVICE, ROOT, INTERFACE, "Notify"); - m.append("/foo"); + while(timeout > 0 && !_next) + { + _bus.process_discard(); + _bus.wait(50000); + timeout -= 50000; + } + return std::move(_next); + } + + private: + static int callback(sd_bus_message *m, void *context, sd_bus_error *) + { + auto *me = static_cast<SignalQueue *>(context); + sd_bus_message_ref(m); + sdbusplus::message::message msg{m}; + me->_next = std::move(msg); + return 0; + } - using var = sdbusplus::message::variant<std::string>; - using inner = std::map<std::string, var>; - using outer = std::map<std::string, inner>; + sdbusplus::bus::bus _bus; + sdbusplus::server::match::match _match; + sdbusplus::message::message _next; +}; - inner i = {{"ExampleProperty1", "test"}}; - outer o = {{"xyz.openbmc_project.Example.Iface1", i}}; +template <typename ...T> +using Object = std::map< + std::string, + std::map< + std::string, + sdbusplus::message::variant<T...>>>; - m.append(o); - auto reply = b.call(m); - auto cleanup = sdbusplus::message::message(reply); - assert(sd_bus_message_get_errno(reply) == 0); +using ObjectPath = std::string; + +/**@brief Find a subset of interfaces and properties in an object. */ +template <typename ...T> +auto hasProperties(const Object<T...> &l, const Object<T...> &r) +{ + Object<T...> result; + std::set_difference( + r.cbegin(), + r.cend(), + l.cbegin(), + l.cend(), + std::inserter(result, result.end())); + return result.empty(); +} + +void runTests(phosphor::inventory::manager::Manager &mgr) +{ + const std::string root{ROOT}; + auto b = sdbusplus::bus::new_default(); + auto notify = [&]() + { + return b.new_method_call( + SERVICE, + ROOT, + INTERFACE, + "Notify"); + }; + + Object<std::string> obj{ + { + "xyz.openbmc_project.Example.Iface1", + {{"ExampleProperty1", "test1"}} + }, + { + "xyz.openbmc_project.Example.Iface2", + {{"ExampleProperty2", "test2"}} + }, + }; + + // Make sure the notify method works. + { + ObjectPath relPath{"/foo"}; + ObjectPath path{root + relPath}; + + SignalQueue queue( + "path='" + root + "',member='InterfacesAdded'"); + + auto m = notify(); + m.append(relPath); + m.append(obj); + b.call(m); + + auto sig{queue.pop()}; + assert(sig); + ObjectPath signalPath; + Object<std::string> signalObject; + sig.read(signalPath); + assert(path == signalPath); + sig.read(signalObject); + assert(hasProperties(signalObject, obj)); + auto moreSignals{queue.pop()}; + assert(!moreSignals); } mgr.shutdown(); + std::cout << "Success!" << std::endl; } int main() { auto mgr = phosphor::inventory::manager::Manager( - sdbusplus::bus::new_system(), + sdbusplus::bus::new_default(), SERVICE, ROOT, INTERFACE); pthread_t t; { - pthread_create(&t, NULL, server_thread, &mgr); + pthread_create(&t, nullptr, server_thread, &mgr); } runTests(mgr); // Wait for server thread to exit. - pthread_join(t, NULL); + pthread_join(t, nullptr); return 0; } |

