~thomas-voss/dbus-cpp/force_gcc_4.7_and_symbols

« back to all changes in this revision

Viewing changes to tests/service_watcher_test.cpp

  • Committer: Tarmac
  • Author(s): Pete Woods
  • Date: 2014-02-03 12:21:44 UTC
  • mfrom: (24.3.36 trunk)
  • Revision ID: tarmac-20140203122144-u15nf8142o7cplj3
Add service watcher class to allow watching DBus name ownership changes.

Approved by PS Jenkins bot, Thomas Voß.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2014 Canonical Ltd.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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/>.
 
15
 *
 
16
 * Authored by: Pete Woods <pete.woods@canonical.com>
 
17
 */
 
18
 
 
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>
 
27
 
 
28
#include <core/dbus/asio/executor.h>
 
29
 
 
30
#include "sig_term_catcher.h"
 
31
#include "test_data.h"
 
32
#include "test_service.h"
 
33
#include "test_service_tiny.h"
 
34
 
 
35
#include <core/testing/cross_process_sync.h>
 
36
#include <core/testing/fork_and_run.h>
 
37
 
 
38
#include <gtest/gtest.h>
 
39
 
 
40
#include <system_error>
 
41
#include <thread>
 
42
 
 
43
namespace dbus = core::dbus;
 
44
 
 
45
namespace
 
46
{
 
47
struct ServiceWatcher : public core::dbus::testing::Fixture
 
48
{
 
49
};
 
50
 
 
51
auto session_bus_config_file =
 
52
        core::dbus::testing::Fixture::default_session_bus_config_file() =
 
53
        core::testing::session_bus_configuration_file();
 
54
 
 
55
auto system_bus_config_file =
 
56
        core::dbus::testing::Fixture::default_system_bus_config_file() =
 
57
        core::testing::system_bus_configuration_file();
 
58
}
 
59
 
 
60
TEST_F(ServiceWatcher, Registration)
 
61
{
 
62
    core::testing::CrossProcessSync client_is_listening_for_service_registration;
 
63
 
 
64
    auto service = [this, &client_is_listening_for_service_registration]()
 
65
    {
 
66
        core::testing::SigTermCatcher sc;
 
67
 
 
68
        EXPECT_EQ(1,
 
69
                          client_is_listening_for_service_registration.wait_for_signal_ready_for(
 
70
                              std::chrono::milliseconds{500}));
 
71
 
 
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);
 
76
 
 
77
        std::thread t{[bus](){ bus->run(); }};
 
78
 
 
79
        sc.wait_for_signal_for(std::chrono::seconds{10});
 
80
 
 
81
        bus->stop();
 
82
 
 
83
        if (t.joinable())
 
84
            t.join();
 
85
 
 
86
        return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
 
87
    };
 
88
 
 
89
    auto client = [this, &client_is_listening_for_service_registration]()
 
90
    {
 
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(); }};
 
95
 
 
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));
 
100
 
 
101
        std::vector<std::pair<std::string, std::string>> owner_changed;
 
102
        unsigned int service_registered = 0;
 
103
        unsigned int service_unregistered = 0;
 
104
 
 
105
        service_watcher->owner_changed().connect(
 
106
            [&owner_changed](const std::string& old_owner, const std::string& new_owner)
 
107
            {
 
108
                owner_changed.push_back({ new_owner, old_owner });
 
109
            });
 
110
        service_watcher->service_registered().connect([bus, &service_registered]()
 
111
            {
 
112
                ++service_registered;
 
113
                bus->stop();
 
114
            });
 
115
        service_watcher->service_unregistered().connect([&service_unregistered]()
 
116
            {
 
117
                ++service_unregistered;
 
118
            });
 
119
 
 
120
        client_is_listening_for_service_registration.try_signal_ready_for(std::chrono::milliseconds{500});
 
121
 
 
122
        if (t.joinable())
 
123
            t.join();
 
124
 
 
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);
 
130
 
 
131
        return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
 
132
    };
 
133
 
 
134
    EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client));
 
135
}
 
136
 
 
137
TEST_F(ServiceWatcher, Unregistration)
 
138
{
 
139
    core::testing::CrossProcessSync client_is_listening_for_service_unregistration;
 
140
 
 
141
    auto service = [this, &client_is_listening_for_service_unregistration]()
 
142
    {
 
143
        auto bus = session_bus();
 
144
        bus->install_executor(core::dbus::asio::make_executor(bus));
 
145
 
 
146
        // Ensure that the client is listening for unregistration before we even
 
147
        // start the service.
 
148
        EXPECT_EQ(1,
 
149
                client_is_listening_for_service_unregistration.wait_for_signal_ready_for(
 
150
                              std::chrono::milliseconds{500}));
 
151
 
 
152
        // We just let this be destroyed immediately
 
153
        dbus::Service::add_service<test::ServiceTiny>(bus);
 
154
 
 
155
        std::thread t{[bus](){ bus->run(); }};
 
156
 
 
157
        bus->stop();
 
158
 
 
159
        if (t.joinable())
 
160
            t.join();
 
161
 
 
162
        return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
 
163
    };
 
164
 
 
165
    auto client = [this, &client_is_listening_for_service_unregistration]()
 
166
    {
 
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(); }};
 
171
 
 
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));
 
176
 
 
177
        std::vector<std::pair<std::string, std::string>> owner_changed;
 
178
        unsigned int service_registered = 0;
 
179
        unsigned int service_unregistered = 0;
 
180
 
 
181
        service_watcher->owner_changed().connect(
 
182
            [&owner_changed](const std::string& old_owner, const std::string& new_owner)
 
183
            {
 
184
                owner_changed.push_back({ new_owner, old_owner });
 
185
            });
 
186
        service_watcher->service_registered().connect([&service_registered]()
 
187
            {
 
188
                ++service_registered;
 
189
            });
 
190
        service_watcher->service_unregistered().connect([bus, &service_unregistered]()
 
191
            {
 
192
                ++service_unregistered;
 
193
                bus->stop();
 
194
            });
 
195
 
 
196
        client_is_listening_for_service_unregistration.try_signal_ready_for(std::chrono::milliseconds{500});
 
197
 
 
198
        if (t.joinable())
 
199
            t.join();
 
200
 
 
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);
 
206
 
 
207
        return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
 
208
    };
 
209
 
 
210
    EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(service, client));
 
211
}