xref: /openbmc/telemetry/tests/src/dbus_environment.hpp (revision f763c9e3bbe0f86a4a41e7bb0dc70bffde0af9b2)
1 #pragma once
2 
3 #include <sdbusplus/asio/object_server.hpp>
4 #include <sdbusplus/asio/property.hpp>
5 
6 #include <future>
7 #include <thread>
8 
9 #include <gmock/gmock.h>
10 
11 class DbusEnvironment : public ::testing::Environment
12 {
13   public:
14     ~DbusEnvironment();
15 
16     void SetUp() override;
17     void TearDown() override;
18     void teardown();
19 
20     static boost::asio::io_context& getIoc();
21     static std::shared_ptr<sdbusplus::asio::connection> getBus();
22     static std::shared_ptr<sdbusplus::asio::object_server> getObjServer();
23     static const char* serviceName();
24     static std::function<void()> setPromise(std::string_view name);
25     static void sleepFor(std::chrono::milliseconds);
26     static std::chrono::milliseconds measureTime(std::function<void()>);
27 
28     static void synchronizeIoc()
29     {
30         while (ioc.poll() > 0)
31         {}
32     }
33 
34     template <class Functor>
35     static void synchronizedPost(Functor&& functor)
36     {
37         boost::asio::post(ioc, std::forward<Functor>(functor));
38         synchronizeIoc();
39     }
40 
41     template <class T, class F>
42     static T waitForFutures(
43         std::vector<std::future<T>> futures, T init, F&& accumulator,
44         std::chrono::milliseconds timeout = std::chrono::seconds(10))
45     {
46         constexpr auto precission = std::chrono::milliseconds(10);
47         auto elapsed = std::chrono::milliseconds(0);
48 
49         auto sum = init;
50         for (auto& future : futures)
51         {
52             while (future.valid() && elapsed < timeout)
53             {
54                 synchronizeIoc();
55 
56                 if (future.wait_for(precission) == std::future_status::ready)
57                 {
58                     sum = accumulator(sum, future.get());
59                 }
60                 else
61                 {
62                     elapsed += precission;
63                 }
64             }
65         }
66 
67         if (elapsed >= timeout)
68         {
69             throw std::runtime_error("Timed out while waiting for future");
70         }
71 
72         return sum;
73     }
74 
75     template <class T>
76     static T waitForFuture(
77         std::future<T> future,
78         std::chrono::milliseconds timeout = std::chrono::seconds(10))
79     {
80         std::vector<std::future<T>> futures;
81         futures.emplace_back(std::move(future));
82 
83         return waitForFutures(
84             std::move(futures), T{},
85             [](auto, const auto& value) { return value; }, timeout);
86     }
87 
88     static bool waitForFuture(
89         std::string_view name,
90         std::chrono::milliseconds timeout = std::chrono::seconds(10));
91 
92     static bool waitForFutures(
93         std::string_view name,
94         std::chrono::milliseconds timeout = std::chrono::seconds(10));
95 
96   private:
97     static std::future<bool> getFuture(std::string_view name);
98 
99     static boost::asio::io_context ioc;
100     static std::shared_ptr<sdbusplus::asio::connection> bus;
101     static std::shared_ptr<sdbusplus::asio::object_server> objServer;
102     static std::map<std::string, std::vector<std::future<bool>>> futures;
103     static bool setUp;
104 };
105