2
* Copyright © 2014 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Pete Woods <pete.woods@canonical.com>
19
#include <core/dbus/dbus.h>
20
#include <core/dbus/fixture.h>
21
#include <core/dbus/object.h>
22
#include <core/dbus/property.h>
23
#include <core/dbus/dbus.h>
24
#include <core/dbus/service_watcher.h>
25
#include <core/dbus/types/stl/tuple.h>
26
#include <core/dbus/types/stl/vector.h>
28
#include <core/dbus/asio/executor.h>
30
#include "sig_term_catcher.h"
31
#include "test_data.h"
32
#include "test_service.h"
33
#include "test_service_tiny.h"
35
#include <core/testing/cross_process_sync.h>
36
#include <core/testing/fork_and_run.h>
38
#include <gtest/gtest.h>
40
#include <system_error>
43
namespace dbus = core::dbus;
47
struct ServiceWatcher : public core::dbus::testing::Fixture
51
auto session_bus_config_file =
52
core::dbus::testing::Fixture::default_session_bus_config_file() =
53
core::testing::session_bus_configuration_file();
55
auto system_bus_config_file =
56
core::dbus::testing::Fixture::default_system_bus_config_file() =
57
core::testing::system_bus_configuration_file();
60
TEST_F(ServiceWatcher, Registration)
62
core::testing::CrossProcessSync client_is_listening_for_service_registration;
64
auto service = [this, &client_is_listening_for_service_registration]()
66
core::testing::SigTermCatcher sc;
69
client_is_listening_for_service_registration.wait_for_signal_ready_for(
70
std::chrono::milliseconds{500}));
72
auto bus = session_bus();
73
bus->install_executor(core::dbus::asio::make_executor(bus));
74
auto service_tiny = dbus::Service::add_service<test::ServiceTiny>(bus);
75
auto service = dbus::Service::add_service<test::Service>(bus);
77
std::thread t{[bus](){ bus->run(); }};
79
sc.wait_for_signal_for(std::chrono::seconds{10});
86
return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
89
auto client = [this, &client_is_listening_for_service_registration]()
91
auto bus = session_bus();
92
auto executor = core::dbus::asio::make_executor(bus);
93
bus->install_executor(executor);
94
std::thread t{[bus](){ bus->run(); }};
96
dbus::DBus daemon(bus);
97
dbus::ServiceWatcher::Ptr service_watcher(
98
daemon.make_service_watcher(dbus::traits::Service<test::Service>::interface_name(),
99
dbus::DBus::WatchMode::registration));
101
std::vector<std::pair<std::string, std::string>> owner_changed;
102
unsigned int service_registered = 0;
103
unsigned int service_unregistered = 0;
105
service_watcher->owner_changed().connect(
106
[&owner_changed](const std::string& old_owner, const std::string& new_owner)
108
owner_changed.push_back({ new_owner, old_owner });
110
service_watcher->service_registered().connect([bus, &service_registered]()
112
++service_registered;
115
service_watcher->service_unregistered().connect([&service_unregistered]()
117
++service_unregistered;
120
client_is_listening_for_service_registration.try_signal_ready_for(std::chrono::milliseconds{500});
125
EXPECT_EQ(1, owner_changed.size());
126
EXPECT_FALSE(owner_changed.at(0).first.empty());
127
EXPECT_TRUE(owner_changed.at(0).second.empty());
128
EXPECT_EQ(1, service_registered);
129
EXPECT_EQ(0, service_unregistered);
131
return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
134
EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client));
137
TEST_F(ServiceWatcher, Unregistration)
139
core::testing::CrossProcessSync client_is_listening_for_service_unregistration;
141
auto service = [this, &client_is_listening_for_service_unregistration]()
143
auto bus = session_bus();
144
bus->install_executor(core::dbus::asio::make_executor(bus));
146
// Ensure that the client is listening for unregistration before we even
147
// start the service.
149
client_is_listening_for_service_unregistration.wait_for_signal_ready_for(
150
std::chrono::milliseconds{500}));
152
// We just let this be destroyed immediately
153
dbus::Service::add_service<test::ServiceTiny>(bus);
155
std::thread t{[bus](){ bus->run(); }};
162
return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
165
auto client = [this, &client_is_listening_for_service_unregistration]()
167
auto bus = session_bus();
168
auto executor = core::dbus::asio::make_executor(bus);
169
bus->install_executor(executor);
170
std::thread t{[bus](){ bus->run(); }};
172
dbus::DBus daemon(bus);
173
dbus::ServiceWatcher::Ptr service_watcher(
174
daemon.make_service_watcher(dbus::traits::Service<test::ServiceTiny>::interface_name(),
175
dbus::DBus::WatchMode::unregistration));
177
std::vector<std::pair<std::string, std::string>> owner_changed;
178
unsigned int service_registered = 0;
179
unsigned int service_unregistered = 0;
181
service_watcher->owner_changed().connect(
182
[&owner_changed](const std::string& old_owner, const std::string& new_owner)
184
owner_changed.push_back({ new_owner, old_owner });
186
service_watcher->service_registered().connect([&service_registered]()
188
++service_registered;
190
service_watcher->service_unregistered().connect([bus, &service_unregistered]()
192
++service_unregistered;
196
client_is_listening_for_service_unregistration.try_signal_ready_for(std::chrono::milliseconds{500});
201
EXPECT_EQ(1, owner_changed.size());
202
EXPECT_TRUE(owner_changed.at(0).first.empty());
203
EXPECT_FALSE(owner_changed.at(0).second.empty());
204
EXPECT_EQ(0, service_registered);
205
EXPECT_EQ(1, service_unregistered);
207
return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
210
EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client));