summaryrefslogtreecommitdiff
path: root/org.genivi.commonapi.core.verification/src/CMAttributeSubscription.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'org.genivi.commonapi.core.verification/src/CMAttributeSubscription.cpp')
-rw-r--r--org.genivi.commonapi.core.verification/src/CMAttributeSubscription.cpp661
1 files changed, 621 insertions, 40 deletions
diff --git a/org.genivi.commonapi.core.verification/src/CMAttributeSubscription.cpp b/org.genivi.commonapi.core.verification/src/CMAttributeSubscription.cpp
index d7e9c9d..4a0c01c 100644
--- a/org.genivi.commonapi.core.verification/src/CMAttributeSubscription.cpp
+++ b/org.genivi.commonapi.core.verification/src/CMAttributeSubscription.cpp
@@ -18,14 +18,18 @@
#include "CommonAPI/CommonAPI.hpp"
#include "v1_0/commonapi/communication/TestInterfaceProxy.hpp"
#include "v1_0/commonapi/communication/TestInterfaceStubDefault.hpp"
+#include "v1_0/commonapi/communication/DaemonStubDefault.hpp"
+#include "stub/CMAttributesStub.h"
-const std::string serviceId = "service-sample";
+const std::string daemonId = "service-sample";
const std::string clientId = "client-sample";
+const std::string serviceId = "test-service";
const std::string domain = "local";
const std::string testAddress = "commonapi.communication.TestInterface";
+const std::string daemonAddress = "commonapi.communication.Daemon";
-const unsigned int wt = 500000;
+const unsigned int wt = 100000;
typedef std::shared_ptr<v1_0::commonapi::communication::TestInterfaceProxy<>> ProxyPtr;
@@ -33,6 +37,8 @@ std::mutex mut;
std::deque<uint32_t> data_queue;
std::condition_variable data_cond;
+using namespace v1_0::commonapi::communication;
+
class SubscriptionHandler {
public:
@@ -65,7 +71,17 @@ public:
/* for test purposes, magic value 99 unsubscribes the attribute. */
if (val == 99) {
- cancelSubscribe();
+
+ // We can't call cancleSubscribe() within the async handler
+ // because it lead to a dead lock with the SomeIP-binding.
+ // Therefore we unsubscribe within the main thread of the test case!
+ //
+ // The reason for the dead lock is because within the async handler
+ // the connection thread is holding the Connection::sendReceiveMutex_
+ // which will locked again when calling Connection::removeEventHandler
+ // which is implicitly called when unsubscribing!
+
+ // cancelSubscribe();
}
}
@@ -93,6 +109,10 @@ public:
return testAttribute_;
}
+ void resetSubcriptedTestAttribute() {
+ testAttribute_ = 0;
+ }
+
std::deque<uint8_t> myQueue_;
private:
@@ -138,6 +158,67 @@ private:
uint8_t notOkAttribute_;
};
+class ThreeCallbackHandler {
+public:
+ ThreeCallbackHandler() :
+ callbackCounter_1_(0),
+ callbackCounter_2_(0),
+ callbackCounter_3_(0),
+ callbackValue_1_(0),
+ callbackValue_2_(0),
+ callbackValue_3_(0) {
+
+ }
+
+ void callback_1(const uint8_t& val) {
+ callbackCounter_1_++;
+ callbackValue_1_ = val;
+ }
+
+ void callback_2(const uint8_t& val) {
+ callbackCounter_2_++;
+ callbackValue_2_ = val;
+ }
+
+ void callback_3(const uint8_t& val) {
+ callbackCounter_3_++;
+ callbackValue_3_ = val;
+ }
+
+ uint8_t getCallbackCounter_1() {
+ return callbackCounter_1_;
+ }
+
+ uint8_t getCallbackCounter_2() {
+ return callbackCounter_2_;
+ }
+
+ uint8_t getCallbackCounter_3() {
+ return callbackCounter_3_;
+ }
+
+ uint8_t getCallbackValue_1() {
+ return callbackValue_1_;
+ }
+
+ uint8_t getCallbackValue_2() {
+ return callbackValue_2_;
+ }
+
+ uint8_t getCallbackValue_3() {
+ return callbackValue_3_;
+ }
+
+private:
+ uint8_t callbackCounter_1_;
+ uint8_t callbackCounter_2_;
+ uint8_t callbackCounter_3_;
+
+ uint8_t callbackValue_1_;
+ uint8_t callbackValue_2_;
+ uint8_t callbackValue_3_;
+};
+
void testSubscription(ProxyPtr pp) {
SubscriptionHandler subscriptionHandler(pp);
@@ -169,19 +250,29 @@ protected:
runtime_ = CommonAPI::Runtime::get();
ASSERT_TRUE((bool)runtime_);
- testProxy_ = runtime_->buildProxy<v1_0::commonapi::communication::TestInterfaceProxy>(domain, testAddress, clientId);
+ testProxy_ = runtime_->buildProxy<TestInterfaceProxy>(domain, testAddress, clientId);
ASSERT_TRUE((bool)testProxy_);
- testStub_ = std::make_shared<v1_0::commonapi::communication::TestInterfaceStubDefault>();
+ testStub_ = std::make_shared<TestInterfaceStubDefault>();
+
+ deregisterService_ = false;
}
void TearDown() {
+ // secure, that service is deregistered by finishing the test
+ if (deregisterService_) {
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+ }
}
std::shared_ptr<CommonAPI::Runtime> runtime_;
- std::shared_ptr<v1_0::commonapi::communication::TestInterfaceProxy<>> testProxy_;
- std::shared_ptr<v1_0::commonapi::communication::TestInterfaceStubDefault> testStub_;
+ std::shared_ptr<TestInterfaceProxy<>> testProxy_;
+ std::shared_ptr<TestInterfaceStubDefault> testStub_;
+
+ bool deregisterService_;
};
class Environment: public ::testing::Environment {
@@ -191,12 +282,17 @@ public:
}
virtual void SetUp() {
+ stubDaemon_ = std::make_shared<DaemonStubDefault>();
+ CommonAPI::Runtime::get()->registerService(domain, daemonAddress, stubDaemon_, daemonId);
}
virtual void TearDown() {
+ CommonAPI::Runtime::get()->unregisterService(domain, DaemonStubDefault::StubInterface::getInterface(),
+ daemonAddress);
}
private:
+ std::shared_ptr<DaemonStubDefault> stubDaemon_;
};
/**
@@ -210,35 +306,58 @@ private:
*/
TEST_F(CMAttributeSubscription, SubscriptionStandard) {
+ deregisterService_ = true;
+
+ uint8_t defaultValue = 33;
+
+ // initialize test stub with default value
+ testStub_->setTestAttributeAttribute(defaultValue);
+
bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
ASSERT_TRUE(serviceRegistered);
- for(unsigned int i = 0; !testProxy_->isAvailable() && i < 100; ++i) {
- usleep(10000);
- }
+ testProxy_->isAvailableBlocking();
ASSERT_TRUE(testProxy_->isAvailable());
SubscriptionHandler subscriptionHandler(testProxy_);
- std::function<void (const uint8_t&)> myCallback = std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
- //CommonAPI::Event<uint8_t>::Subscription subscribedListener =
- testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback);
+ std::function<void (const uint8_t&)> myCallback =
+ std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
+
+ CommonAPI::Event<uint8_t>::Subscription subscribedListener =
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback);
const uint8_t testNumber = 10;
for (uint8_t i=1; i<testNumber+1; i++) {
- testStub_->setTestAttributeAttribute(i);
+ usleep(100000);
+ testStub_->setTestAttributeAttribute(i);
}
usleep(wt);
- ASSERT_EQ(subscriptionHandler.myQueue_.size(), testNumber);
+ ASSERT_EQ(subscriptionHandler.myQueue_.size(), testNumber + 1); // + 1 due to the reason, that by subscribtion the current value is returned
- uint8_t t = 1;
+ uint8_t t = 0;
for(std::deque<uint8_t>::iterator it = subscriptionHandler.myQueue_.begin(); it != subscriptionHandler.myQueue_.end(); ++it) {
- EXPECT_EQ(*it, t);
- t++;
+ if (t == 0) {
+ EXPECT_EQ(*it, defaultValue);
+ t++;
+ } else {
+ EXPECT_EQ(*it, t);
+ t++;
+ }
}
- runtime_->unregisterService(domain, v1_0::commonapi::communication::TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().unsubscribe(subscribedListener);
+
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ usleep(wt);
+
+ deregisterService_ = !isUnregistered;
}
+
/**
* @test Subscription test with subscription on available-event.
* - Subscribe for available-event.
@@ -252,7 +371,8 @@ TEST_F(CMAttributeSubscription, SubscriptionOnAvailable) {
SubscriptionHandler subscriptionHandler(testProxy_);
- std::function<void (CommonAPI::AvailabilityStatus)> callbackAvailabilityStatus = std::bind(&SubscriptionHandler::receiveServiceAvailable, &subscriptionHandler, std::placeholders::_1);
+ std::function<void (CommonAPI::AvailabilityStatus)> callbackAvailabilityStatus =
+ std::bind(&SubscriptionHandler::receiveServiceAvailable, &subscriptionHandler, std::placeholders::_1);
testProxy_->getProxyStatusEvent().subscribe(callbackAvailabilityStatus);
testStub_->setTestAttributeAttribute(1);
@@ -262,11 +382,14 @@ TEST_F(CMAttributeSubscription, SubscriptionOnAvailable) {
bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
ASSERT_TRUE(serviceRegistered);
usleep(wt);
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
testStub_->setTestAttributeAttribute(2);
usleep(wt);
ASSERT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 2);
- bool serviceUnregistered = runtime_->unregisterService(domain, v1_0::commonapi::communication::TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ bool serviceUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
ASSERT_TRUE(serviceUnregistered);
usleep(wt);
ASSERT_EQ(subscriptionHandler.getAvailabilityStatus(), CommonAPI::AvailabilityStatus::NOT_AVAILABLE);
@@ -307,7 +430,8 @@ TEST_F(CMAttributeSubscription, SubscriptionMultithreading) {
usleep(wt);
- bool serviceUnregistered = runtime_->unregisterService(domain, v1_0::commonapi::communication::TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ bool serviceUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
ASSERT_TRUE(serviceUnregistered);
uint32_t data = 0;
@@ -354,15 +478,14 @@ TEST_F(CMAttributeSubscription, SubscriptionUnsubscribeFromCallback) {
bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
ASSERT_TRUE(serviceRegistered);
- for(unsigned int i = 0; !testProxy_->isAvailable() && i < 100; ++i) {
- usleep(10000);
- }
+ testProxy_->isAvailableBlocking();
ASSERT_TRUE(testProxy_->isAvailable());
SubscriptionHandler subscriptionHandler(testProxy_);
- std::function<void (const uint8_t&)> myCallback = std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
- subscriptionHandler.startSubscribe();
+ std::function<void (const uint8_t&)> myCallback = std::bind(&SubscriptionHandler::myCallback,
+ &subscriptionHandler, std::placeholders::_1);
+ subscriptionHandler.startSubscribe();
testStub_->setTestAttributeAttribute(42);
usleep(wt);
@@ -372,11 +495,16 @@ TEST_F(CMAttributeSubscription, SubscriptionUnsubscribeFromCallback) {
usleep(wt);
EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 99);
+ subscriptionHandler.cancelSubscribe();
+ usleep(wt);
+
testStub_->setTestAttributeAttribute(250);
usleep(wt);
EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 99);
- runtime_->unregisterService(domain, v1_0::commonapi::communication::TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
}
/**
@@ -395,8 +523,10 @@ TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeTwoCallbacksCoexistent) {
CommonAPI::Event<uint8_t>::Subscription subscribedListenerCallOk;
CommonAPI::Event<uint8_t>::Subscription subscribedListenerCallNotOk;
- std::function<void (uint8_t)> callbackOk = std::bind(&SubscribeUnsubscribeHandler::okCallback, &subUnsubHandler, std::placeholders::_1);
- std::function<void (uint8_t)> callbackNotOk = std::bind(&SubscribeUnsubscribeHandler::notOkCallback, &subUnsubHandler, std::placeholders::_1);
+ std::function<void (uint8_t)> callbackOk =
+ std::bind(&SubscribeUnsubscribeHandler::okCallback, &subUnsubHandler, std::placeholders::_1);
+ std::function<void (uint8_t)> callbackNotOk =
+ std::bind(&SubscribeUnsubscribeHandler::notOkCallback, &subUnsubHandler, std::placeholders::_1);
subscribedListenerCallOk = testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(callbackOk);
subscribedListenerCallNotOk = testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(callbackNotOk);
@@ -408,7 +538,10 @@ TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeTwoCallbacksCoexistent) {
bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
ASSERT_TRUE(serviceRegistered);
- usleep(wt);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
testStub_->setTestAttributeAttribute(2);
usleep(wt);
EXPECT_EQ(subUnsubHandler.getSubscribedOkAttribute(), 2);
@@ -422,7 +555,7 @@ TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeTwoCallbacksCoexistent) {
EXPECT_EQ(subUnsubHandler.getSubscribedOkAttribute(), 2);
EXPECT_EQ(subUnsubHandler.getSubscribedNotOkAttribute(), 2);
- bool serviceUnregistered = runtime_->unregisterService(domain, v1_0::commonapi::communication::TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ bool serviceUnregistered = runtime_->unregisterService(domain, TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
ASSERT_TRUE(serviceUnregistered);
usleep(wt);
}
@@ -442,12 +575,16 @@ TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeImmediatelyUnsubscribing)
CommonAPI::Event<uint8_t>::Subscription subscribedListenerCallOk;
CommonAPI::Event<uint8_t>::Subscription subscribedListenerCallNotOk;
- std::function<void (uint8_t)> callbackOk = std::bind(&SubscribeUnsubscribeHandler::okCallback, &subUnsubHandler, std::placeholders::_1);
- std::function<void (uint8_t)> callbackNotOk = std::bind(&SubscribeUnsubscribeHandler::notOkCallback, &subUnsubHandler, std::placeholders::_1);
+ std::function<void (uint8_t)> callbackOk =
+ std::bind(&SubscribeUnsubscribeHandler::okCallback, &subUnsubHandler, std::placeholders::_1);
+ std::function<void (uint8_t)> callbackNotOk =
+ std::bind(&SubscribeUnsubscribeHandler::notOkCallback, &subUnsubHandler, std::placeholders::_1);
bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
ASSERT_TRUE(serviceRegistered);
- usleep(wt);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
// subscribe ok callback
subscribedListenerCallOk = testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(callbackOk);
@@ -470,7 +607,7 @@ TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeImmediatelyUnsubscribing)
testProxy_->getTestAttributeAttribute().getChangedEvent().unsubscribe(subscribedListenerCallNotOk);
testProxy_->getTestAttributeAttribute().getChangedEvent().unsubscribe(subscribedListenerCallOk);
- bool serviceUnregistered = runtime_->unregisterService(domain, v1_0::commonapi::communication::TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ bool serviceUnregistered = runtime_->unregisterService(domain, TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
ASSERT_TRUE(serviceUnregistered);
usleep(wt);
}
@@ -495,12 +632,16 @@ TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeSequentially) {
CommonAPI::Event<uint8_t>::Subscription subscribedListenerCallOk;
CommonAPI::Event<uint8_t>::Subscription subscribedListenerCallNotOk;
- std::function<void (uint8_t)> callbackOk = std::bind(&SubscribeUnsubscribeHandler::okCallback, &subUnsubHandler, std::placeholders::_1);
- std::function<void (uint8_t)> callbackNotOk = std::bind(&SubscribeUnsubscribeHandler::notOkCallback, &subUnsubHandler, std::placeholders::_1);
+ std::function<void (uint8_t)> callbackOk =
+ std::bind(&SubscribeUnsubscribeHandler::okCallback, &subUnsubHandler, std::placeholders::_1);
+ std::function<void (uint8_t)> callbackNotOk =
+ std::bind(&SubscribeUnsubscribeHandler::notOkCallback, &subUnsubHandler, std::placeholders::_1);
bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
ASSERT_TRUE(serviceRegistered);
- usleep(wt);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
// subscribe ok and notOk callback
subscribedListenerCallOk = testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(callbackOk);
@@ -527,11 +668,451 @@ TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeSequentially) {
EXPECT_EQ(subUnsubHandler.getSubscribedOkAttribute(), 12);
EXPECT_EQ(subUnsubHandler.getSubscribedNotOkAttribute(), 14);
- bool serviceUnregistered = runtime_->unregisterService(domain, v1_0::commonapi::communication::TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ bool serviceUnregistered = runtime_->unregisterService(domain, TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
ASSERT_TRUE(serviceUnregistered);
usleep(wt);
}
+
+/**
+ * @test Test of behaviour in case unsubscribe is called two times
+ * - set default value
+ * - register service
+ * - subscribe for the attribute
+ * - current value must be communicated to the proxy
+ * - value of attribute is changed
+ * - changed value must be communicated to the proxy
+ * - proxy unsubscribes for the attribute
+ * - value of attribute is changed
+ * - changed value must not be communicated to the proxy
+ * - proxy unsubscribes again for the attribute
+ * - value of attribute is changed
+ * - changed value must not be communicated to the proxy
+ * - unregister service
+ */
+TEST_F(CMAttributeSubscription, SubscribeAndUnsubscribeUnsubscribe) {
+
+ testStub_->setTestAttributeAttribute(42);
+
+ bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
+ SubscriptionHandler subscriptionHandler(testProxy_);
+ std::function<void (const uint8_t&)> myCallback =
+ std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
+
+ CommonAPI::Event<uint8_t>::Subscription subscribedListener =
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback);
+
+ usleep(wt);
+
+ // check for initial value
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 42);
+
+ testStub_->setTestAttributeAttribute(12);
+ usleep(wt);
+
+ // check for changed value
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 12);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().unsubscribe(subscribedListener);
+
+ testStub_->setTestAttributeAttribute(24);
+ usleep(wt);
+
+ // value must not be changed
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 12);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().unsubscribe(subscribedListener);
+
+ testStub_->setTestAttributeAttribute(26);
+ usleep(wt);
+
+ // value must not be changed
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 12);
+
+ bool serviceUnregistered = runtime_->unregisterService(domain, TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(serviceUnregistered);
+ usleep(wt);
+}
+
+/**
+ * @test Test of subscribing in case that service is not available
+ * - set default value
+ * - subscribe for the attribute
+ * - no value is communicated to the proxy
+ * - register service
+ * - current value must be communicated to the proxy
+ * - value of attribute is changed
+ * - changed value must be communicated to the proxy
+ * - unregister service
+ */
+TEST_F(CMAttributeSubscription, SubscribeServiceNotAvailable) {
+
+ deregisterService_ = true;
+
+ uint8_t defaultValue = 33;
+
+ // initialize test stub with default value
+ testStub_->setTestAttributeAttribute(defaultValue);
+
+ // subscribe for attribute change by the proxy
+ SubscriptionHandler subscriptionHandler(testProxy_);
+ std::function<void (const uint8_t&)> myCallback =
+ std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback);
+
+ usleep(wt);
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 0);
+
+ // register service
+ bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
+ usleep(wt);
+
+ // check received attribute value
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), defaultValue);
+
+ int8_t newValue = 123;
+
+ testStub_->setTestAttributeAttribute(newValue);
+ usleep(wt);
+
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), newValue);
+
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ deregisterService_ = !isUnregistered;
+}
+
+/**
+ * @test Test of unregister a service in case a proxy is subscribed for an attribute of this service.
+ * During the unregistered time of the service the value of the attribute is changed.
+ * - register service
+ * - proxy subscribes for an attribute of the service
+ * - value of attribute is set
+ * - changed value must be communicated to the proxy
+ * - unregister service
+ * - value of attribute is changed
+ * - changed value must not be communicated to the proxy
+ * - register service
+ * - current attribute value must be communicated to the proxy
+ * - value of attribute is changed
+ * - changed value must be communicated to the proxy
+ * - unregister service
+ */
+TEST_F(CMAttributeSubscription, SubscribeUnregisterSetValueRegisterService) {
+ deregisterService_ = true;
+
+ uint8_t firstValue = 35;
+ uint8_t secondValue = 43;
+ uint8_t thirdValue = 198;
+
+ // register service
+ bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
+ // subscribe for attribute change by the proxy
+ SubscriptionHandler subscriptionHandler(testProxy_);
+ std::function<void (const uint8_t&)> myCallback =
+ std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback);
+
+ // initialize test stub with default value
+ testStub_->setTestAttributeAttribute(firstValue);
+ usleep(wt);
+
+ // check received attribute value
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), firstValue);
+
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+ deregisterService_ = !isUnregistered;
+
+ testStub_->setTestAttributeAttribute(secondValue);
+ usleep(wt);
+
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), firstValue);
+
+ // register service
+ serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ usleep(wt);
+
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), secondValue);
+
+ testStub_->setTestAttributeAttribute(thirdValue);
+ usleep(wt);
+
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), thirdValue);
+
+ isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ deregisterService_ = !isUnregistered;
+}
+
+/**
+ * @test Test of unregister a service in case a proxy is subscribed for an attribute of this service.
+ * During the unregistered time of the service the value of the attribute is not changed.
+ * - register service
+ * - proxy subscribes for an attribute of the service
+ * - value of attribute is set
+ * - changed value must be communicated to the proxy
+ * - unregister service
+ * - register service
+ * - current attribute value must be communicated to the proxy
+ * - value of attribute is changed
+ * - changed value must be communicated to the proxy
+ * - unregister service
+ */
+TEST_F(CMAttributeSubscription, SubscribeUnregisterNoValueSetRegisterService) {
+
+ deregisterService_ = true;
+
+ uint8_t firstValue = 35;
+ uint8_t secondValue = 43;
+
+ // register service
+ bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
+ // subscribe for attribute change by the proxy
+ SubscriptionHandler subscriptionHandler(testProxy_);
+ std::function<void (const uint8_t&)> myCallback =
+ std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback);
+
+ // initialize test stub with default value
+ testStub_->setTestAttributeAttribute(firstValue);
+ usleep(wt);
+
+ // check received attribute value
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), firstValue);
+
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ subscriptionHandler.resetSubcriptedTestAttribute();
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), 0);
+
+ // register service
+ serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ usleep(wt);
+
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), firstValue);
+
+ testStub_->setTestAttributeAttribute(secondValue);
+ usleep(wt);
+
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), secondValue);
+
+ isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ deregisterService_ = !isUnregistered;
+}
+
+/**
+ * @test Test of subscribing a second proxy a little bit later
+ * - proxy subscribes for an attribute of the service
+ * - register service
+ * - initial value must be communicated to the proxy
+ * - create a second proxy
+ * - second proxy subscribes for the same attribute of the service
+ * - current attribute value must be communicated to the proxy
+ * - value of attribute is changed
+ * - changed value must be communicated to both proxies
+ * - unregister service
+ */
+TEST_F(CMAttributeSubscription, SubscribeSecondProxyLater) {
+
+ deregisterService_ = true;
+
+ uint8_t defaultValue = 33;
+
+ // initialize test stub with default value
+ testStub_->setTestAttributeAttribute(defaultValue);
+
+ // subscribe for attribute change by the proxy
+ SubscriptionHandler subscriptionHandler(testProxy_);
+ std::function<void (const uint8_t&)> myCallback =
+ std::bind(&SubscriptionHandler::myCallback, &subscriptionHandler, std::placeholders::_1);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback);
+
+ // register service
+ bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
+ usleep(wt);
+
+ // check received attribute value
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), defaultValue);
+
+ // create second proxy
+ std::shared_ptr<TestInterfaceProxy<>> secondTestProxy =
+ runtime_->buildProxy<TestInterfaceProxy>(domain, testAddress, clientId);
+ ASSERT_TRUE((bool)secondTestProxy);
+
+ SubscriptionHandler secondSubscriptionHandler(secondTestProxy);
+ std::function<void (const uint8_t&)> secondMyCallback =
+ std::bind(&SubscriptionHandler::myCallback, &secondSubscriptionHandler, std::placeholders::_1);
+
+ secondTestProxy->getTestAttributeAttribute().getChangedEvent().subscribe(secondMyCallback);
+
+ usleep(wt);
+
+ EXPECT_EQ(secondSubscriptionHandler.getSubscriptedTestAttribute(), defaultValue);
+
+ int8_t newValue = 123;
+
+ testStub_->setTestAttributeAttribute(newValue);
+ usleep(wt);
+
+ EXPECT_EQ(subscriptionHandler.getSubscriptedTestAttribute(), newValue);
+ EXPECT_EQ(secondSubscriptionHandler.getSubscriptedTestAttribute(), newValue);
+
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ deregisterService_ = !isUnregistered;
+}
+
+/**
+ * @test Test of subscribing three callbacks before registering the service
+ * - proxy subscribes three callbacks for an attribute of the service
+ * - register service
+ * - initial value must be communicated to every callback
+ */
+TEST_F(CMAttributeSubscription, SubscribeThreeCallbacksServiceNotAvailable) {
+
+ deregisterService_ = true;
+
+ ThreeCallbackHandler threeCallbackHandler;
+
+ uint8_t defaultValue = 33;
+
+ // initialize test stub with default value
+ testStub_->setTestAttributeAttribute(defaultValue);
+
+ std::function<void (const uint8_t&)> myCallback1 =
+ std::bind(&ThreeCallbackHandler::callback_1, &threeCallbackHandler, std::placeholders::_1);
+ std::function<void (const uint8_t&)> myCallback2 =
+ std::bind(&ThreeCallbackHandler::callback_2, &threeCallbackHandler, std::placeholders::_1);
+ std::function<void (const uint8_t&)> myCallback3 =
+ std::bind(&ThreeCallbackHandler::callback_3, &threeCallbackHandler, std::placeholders::_1);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback1);
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback2);
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback3);
+
+ usleep(wt);
+
+ // register service
+ bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
+ usleep(100000);
+
+ EXPECT_EQ(1, threeCallbackHandler.getCallbackCounter_1());
+ EXPECT_EQ(1, threeCallbackHandler.getCallbackCounter_2());
+ EXPECT_EQ(1, threeCallbackHandler.getCallbackCounter_3());
+
+ EXPECT_EQ(defaultValue, threeCallbackHandler.getCallbackValue_1());
+ EXPECT_EQ(defaultValue, threeCallbackHandler.getCallbackValue_2());
+ EXPECT_EQ(defaultValue, threeCallbackHandler.getCallbackValue_3());
+
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ deregisterService_ = !isUnregistered;
+}
+
+/**
+ * @test Test of subscribing three callbacks after registering the service
+ * - register service
+ * - proxy subscribes three callbacks for an attribute of the service
+ * - initial value must be communicated to every callback
+ */
+TEST_F(CMAttributeSubscription, SubscribeThreeCallbacksServiceAvailable) {
+ deregisterService_ = true;
+
+ uint8_t defaultValue = 35;
+
+ ThreeCallbackHandler threeCallbackHandler;
+
+ testStub_->setTestAttributeAttribute(defaultValue);
+ usleep(wt);
+
+ // register service
+ bool serviceRegistered = runtime_->registerService(domain, testAddress, testStub_, serviceId);
+ ASSERT_TRUE(serviceRegistered);
+
+ testProxy_->isAvailableBlocking();
+ ASSERT_TRUE(testProxy_->isAvailable());
+
+ std::function<void (const uint8_t&)> myCallback1 =
+ std::bind(&ThreeCallbackHandler::callback_1, &threeCallbackHandler, std::placeholders::_1);
+ std::function<void (const uint8_t&)> myCallback2 =
+ std::bind(&ThreeCallbackHandler::callback_2, &threeCallbackHandler, std::placeholders::_1);
+ std::function<void (const uint8_t&)> myCallback3 =
+ std::bind(&ThreeCallbackHandler::callback_3, &threeCallbackHandler, std::placeholders::_1);
+
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback1);
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback2);
+ testProxy_->getTestAttributeAttribute().getChangedEvent().subscribe(myCallback3);
+
+ usleep(100000);
+
+ EXPECT_EQ(1, threeCallbackHandler.getCallbackCounter_1());
+ EXPECT_EQ(1, threeCallbackHandler.getCallbackCounter_2());
+ EXPECT_EQ(1, threeCallbackHandler.getCallbackCounter_3());
+
+ EXPECT_EQ(defaultValue, threeCallbackHandler.getCallbackValue_1());
+ EXPECT_EQ(defaultValue, threeCallbackHandler.getCallbackValue_2());
+ EXPECT_EQ(defaultValue, threeCallbackHandler.getCallbackValue_3());
+
+ bool isUnregistered = runtime_->unregisterService(domain,
+ TestInterfaceStubDefault::StubInterface::getInterface(), testAddress);
+ ASSERT_TRUE(isUnregistered);
+
+ deregisterService_ = !isUnregistered;
+}
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
::testing::AddGlobalTestEnvironment(new Environment());