tests: fix blocking semantic in DBusProxyTest
[profile/ivi/common-api-dbus-runtime.git] / src / test / DBusProxyTest.cpp
1 /* Copyright (C) 2013 BMW Group
2  * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
3  * Author: Juergen Gehring (juergen.gehring@bmw.de)
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef _GLIBCXX_USE_NANOSLEEP
8 #define _GLIBCXX_USE_NANOSLEEP
9 #endif
10
11 #include <CommonAPI/DBus/DBusInputStream.h>
12 #include <CommonAPI/DBus/DBusMessage.h>
13 #include <CommonAPI/DBus/DBusProxy.h>
14 #include <CommonAPI/DBus/DBusConnection.h>
15 #include <CommonAPI/DBus/DBusStubAdapter.h>
16 #include <CommonAPI/DBus/DBusUtils.h>
17
18 #include <commonapi/tests/TestInterfaceDBusProxy.h>
19 #include <commonapi/tests/TestInterfaceDBusStubAdapter.h>
20 #include <commonapi/tests/TestInterfaceStubDefault.h>
21
22 #include <gtest/gtest.h>
23
24 #include <algorithm>
25 #include <cstdint>
26 #include <iostream>
27 #include <string>
28 #include <thread>
29 #include <vector>
30
31
32 static const std::string commonApiAddress = "local:CommonAPI.DBus.tests.DBusProxyTestInterface:CommonAPI.DBus.tests.DBusProxyTestService";
33 static const std::string commonApiServiceName = "CommonAPI.DBus.tests.DBusProxyTestInterface";
34 static const std::string interfaceName = "CommonAPI.DBus.tests.DBusProxyTestInterface";
35 static const std::string busName = "CommonAPI.DBus.tests.DBusProxyTestService";
36 static const std::string objectPath = "/CommonAPI/DBus/tests/DBusProxyTestService";
37
38
39 class ProxyTest: public ::testing::Test {
40 protected:
41
42     virtual void TearDown() {
43         proxyDBusConnection_->disconnect();
44
45         stubAdapter_.reset();
46
47         if (stubDBusConnection_) {
48             if (stubDBusConnection_->isConnected()) {
49                 // uses dbus read_write_dispatch() which might dispatch events, which might cause a dead lock
50                 // stubDBusConnection_->releaseServiceName(busName);
51                 stubDBusConnection_->disconnect();
52             }
53             stubDBusConnection_.reset();
54         }
55     }
56
57     void SetUp() {
58         proxyDBusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus();
59         ASSERT_TRUE(proxyDBusConnection_->connect());
60
61         proxy_ = std::make_shared<commonapi::tests::TestInterfaceDBusProxy>(
62                         commonApiAddress,
63                         interfaceName,
64                         busName,
65                         objectPath,
66                         proxyDBusConnection_);
67     }
68
69     void registerTestStub() {
70         stubDBusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus();
71         ASSERT_TRUE(stubDBusConnection_->connect());
72
73         ASSERT_TRUE(stubDBusConnection_->requestServiceNameAndBlock(busName));
74
75         auto stubDefault = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
76         stubAdapter_ = std::make_shared<commonapi::tests::TestInterfaceDBusStubAdapter>(
77                         commonApiAddress,
78                         interfaceName,
79                         busName,
80                         objectPath,
81                         stubDBusConnection_,
82                         stubDefault);
83         stubAdapter_->init();
84     }
85
86     void proxyRegisterForAvailabilityStatus() {
87         proxyAvailabilityStatus_ = CommonAPI::AvailabilityStatus::UNKNOWN;
88
89         proxy_->getProxyStatusEvent().subscribe([&](const CommonAPI::AvailabilityStatus& availabilityStatus) {
90             proxyAvailabilityStatus_ = availabilityStatus;
91         });
92     }
93
94     bool proxyWaitForAvailabilityStatus(const CommonAPI::AvailabilityStatus& availabilityStatus) const {
95         std::chrono::milliseconds loopWaitDuration(100);
96
97         if (proxyAvailabilityStatus_ == availabilityStatus)
98             return true;
99
100         for (int i = 0; i < 10; i++) {
101             std::this_thread::sleep_for(loopWaitDuration);
102
103             if (proxyAvailabilityStatus_ == availabilityStatus)
104                 return true;
105         }
106
107         return false;
108     }
109
110     std::shared_ptr<CommonAPI::DBus::DBusConnection> proxyDBusConnection_;
111     std::shared_ptr<commonapi::tests::TestInterfaceDBusProxy> proxy_;
112     CommonAPI::AvailabilityStatus proxyAvailabilityStatus_;
113
114     std::shared_ptr<CommonAPI::DBus::DBusConnection> stubDBusConnection_;
115     std::shared_ptr<commonapi::tests::TestInterfaceDBusStubAdapter> stubAdapter_;
116 };
117
118 TEST_F(ProxyTest, HasCorrectConnectionName) {
119   std::string actualName = proxy_->getDBusBusName();
120   EXPECT_EQ(busName, actualName);
121 }
122
123 TEST_F(ProxyTest, HasCorrectObjectPath) {
124   std::string actualPath = proxy_->getDBusObjectPath();
125   EXPECT_EQ(objectPath, actualPath);
126 }
127
128 TEST_F(ProxyTest, HasCorrectInterfaceName) {
129   std::string actualName = proxy_->getInterfaceName();
130   EXPECT_EQ(interfaceName, actualName);
131 }
132
133 TEST_F(ProxyTest, IsNotAvailable) {
134         bool isAvailable = proxy_->isAvailable();
135         EXPECT_FALSE(isAvailable);
136 }
137
138 TEST_F(ProxyTest, ServiceRegistry) {
139         std::shared_ptr<CommonAPI::DBus::DBusProxyConnection> connection = proxy_->getDBusConnection();
140         auto registry = connection->getDBusServiceRegistry();
141         ASSERT_FALSE(!registry);
142 }
143
144 TEST_F(ProxyTest, DBusProxyStatusEventBeforeServiceIsRegistered) {
145     proxyRegisterForAvailabilityStatus();
146
147     ASSERT_NE(proxyAvailabilityStatus_, CommonAPI::AvailabilityStatus::AVAILABLE);
148
149     registerTestStub();
150
151     ASSERT_TRUE(proxyWaitForAvailabilityStatus(CommonAPI::AvailabilityStatus::AVAILABLE));
152
153     stubDBusConnection_->disconnect();
154
155     ASSERT_TRUE(proxyWaitForAvailabilityStatus(CommonAPI::AvailabilityStatus::NOT_AVAILABLE));
156 }
157
158 TEST_F(ProxyTest, DBusProxyStatusEventAfterServiceIsRegistered) {
159     proxyDBusConnection_->disconnect();
160
161     registerTestStub();
162
163     ASSERT_TRUE(proxyDBusConnection_->connect());
164
165     proxyRegisterForAvailabilityStatus();
166
167     ASSERT_TRUE(proxyWaitForAvailabilityStatus(CommonAPI::AvailabilityStatus::AVAILABLE));
168
169     stubDBusConnection_->disconnect();
170
171     ASSERT_TRUE(proxyWaitForAvailabilityStatus(CommonAPI::AvailabilityStatus::NOT_AVAILABLE));
172 }
173
174 TEST_F(ProxyTest, ServiceStatus) {
175     proxyDBusConnection_->requestServiceNameAndBlock(busName);
176
177     std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stubDefault = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
178     std::shared_ptr<commonapi::tests::TestInterfaceDBusStubAdapter> stubAdapter =  std::make_shared<commonapi::tests::TestInterfaceDBusStubAdapter>(
179                     commonApiAddress,
180                     interfaceName,
181                     busName,
182                     objectPath,
183                     proxyDBusConnection_,
184                     stubDefault);
185
186     stubAdapter->init();
187
188     auto testConnection = CommonAPI::DBus::DBusConnection::getSessionBus();
189     testConnection->connect();
190
191         std::vector<std::string> actuallyAvailableServices;
192         actuallyAvailableServices = testConnection->getDBusServiceRegistry()->getAvailableServiceInstances(commonApiServiceName,
193                         "local");
194
195         auto found = std::find(actuallyAvailableServices.begin(), actuallyAvailableServices.end(), commonApiAddress);
196
197         ASSERT_TRUE(actuallyAvailableServices.begin() != actuallyAvailableServices.end());
198         ASSERT_TRUE(found != actuallyAvailableServices.end());
199
200         testConnection->disconnect();
201 }
202
203 TEST_F(ProxyTest, isServiceInstanceAlive) {
204     registerTestStub();
205
206     bool isInstanceAlive = proxyDBusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(interfaceName, busName, objectPath);
207
208     for (int i = 0; !isInstanceAlive && i < 10; i++) {
209         std::this_thread::sleep_for(std::chrono::milliseconds(200));
210         isInstanceAlive = proxyDBusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(interfaceName, busName, objectPath);
211     }
212
213     EXPECT_TRUE(isInstanceAlive);
214 }
215
216 TEST_F(ProxyTest, IsAvailableBlocking) {
217     registerTestStub();
218
219     // blocking in terms of "if it's still uknown"
220     bool isAvailable = proxy_->isAvailableBlocking();
221     for (int i = 0; !isAvailable && i < 10; i++) {
222         std::this_thread::sleep_for(std::chrono::milliseconds(200));
223         isAvailable = proxy_->isAvailableBlocking();
224     }
225
226     EXPECT_TRUE(isAvailable);
227 }
228
229 TEST_F(ProxyTest, HasNecessaryAttributesAndEvents) {
230         CommonAPI::InterfaceVersionAttribute& versionAttribute = (proxy_->getInterfaceVersionAttribute());
231         CommonAPI::ProxyStatusEvent& statusEvent = (proxy_->getProxyStatusEvent());
232 }
233
234 TEST_F(ProxyTest, IsConnected) {
235   ASSERT_TRUE(proxy_->getDBusConnection()->isConnected());
236 }
237
238 TEST_F(ProxyTest, TestInterfaceVersionAttribute) {
239         CommonAPI::InterfaceVersionAttribute& versionAttribute = proxy_->getInterfaceVersionAttribute();
240         CommonAPI::Version version;
241         CommonAPI::CallStatus status = versionAttribute.getValue(version);
242         ASSERT_EQ(CommonAPI::CallStatus::NOT_AVAILABLE, status);
243 }
244
245 TEST_F(ProxyTest, AsyncCallbacksAreCalledIfServiceNotAvailable) {
246     commonapi::tests::DerivedTypeCollection::TestEnumExtended2 testInputStruct;
247     commonapi::tests::DerivedTypeCollection::TestMap testInputMap;
248     bool wasCalled = false;
249     proxy_->testDerivedTypeMethodAsync(testInputStruct, testInputMap, [&] (const CommonAPI::CallStatus& callStatus,
250                                                                           const commonapi::tests::DerivedTypeCollection::TestEnumExtended2&,
251                                                                           const commonapi::tests::DerivedTypeCollection::TestMap&) {
252                     ASSERT_EQ(callStatus, CommonAPI::CallStatus::NOT_AVAILABLE);
253                     wasCalled = true;
254             }
255     );
256     sleep(1);
257     ASSERT_TRUE(wasCalled);
258 }
259
260 int main(int argc, char** argv) {
261         ::testing::InitGoogleTest(&argc, argv);
262         return RUN_ALL_TESTS();
263 }