void * AgentConsolidatorTest::create (void *args) { TestArgs *test_args = (TestArgs *) args; AgentConsolidator *cons = test_args->cons; AgentConsolidatorHandle *handle; SubscriptionRequest request; SubscriptionRequest system_accepted_request; telemetry::Path *path; // Build a request path = request.add_path_list(); path->set_path("firewall"); path = request.add_path_list(); path->set_path("port"); // Add it to the consolidator id_idx_t subscription_id = test_args->id; handle = cons->addRequest(subscription_id, &request, &system_accepted_request); // Sleep randomly between 0 to 4 seconds sleep(rand()%5); // Now remove it cons->removeRequest(handle); return NULL; }
TEST_F(AgentConsolidatorTest, add) { AgentConsolidatorHandle *handle; SubscriptionRequest request; SubscriptionRequest system_accepted_request; telemetry::Path *path; // Build a request of valid paths path = request.add_path_list(); path->set_path("firewall"); path = request.add_path_list(); path->set_path("port"); // Add it to the consolidator handle = cons->addRequest(61, &request, &system_accepted_request); EXPECT_TRUE(handle != NULL); EXPECT_EQ(2, cons->getSystemRequestCount()); EXPECT_EQ(1, cons->getAddCount()); EXPECT_EQ(0, cons->getErrors()); for (int i = 0; i < request.path_list_size(); i++) { EXPECT_STREQ(request.path_list(i).path().c_str(), system_accepted_request.path_list(i).path().c_str()); } // Simple check get call is good SubscriptionRequest *test_ptr; test_ptr = cons->getRequest(handle, false); EXPECT_TRUE(test_ptr != NULL); // Remove it now cons->removeRequest(handle); EXPECT_EQ(0, cons->getSystemRequestCount()); EXPECT_EQ(1, cons->getRemCount()); EXPECT_EQ(0, cons->getErrors()); }
/** * Trigger: The dispatcher receives a SubscriptionRequest. * Expected: The PublicationManager creates a PublisherRunnable and polls * the MockCaller for the attribute. */ TEST_F(SubscriptionTest, receive_subscriptionRequestAndPollAttribute) { qRegisterMetaType<OnChangeWithKeepAliveSubscriptionQos>("OnChangeWithKeepAliveSubscriptionQos"); qRegisterMetaType<SubscriptionRequest>("SubscriptionRequest"); // Use a semaphore to count and wait on calls to the mockRequestCaller QSemaphore semaphore(0); EXPECT_CALL(*mockRequestCaller, getLocation(_, _)) .WillRepeatedly(ReleaseSemaphore(&semaphore)); QString attributeName = "Location"; auto subscriptionQos = QSharedPointer<SubscriptionQos>(new OnChangeWithKeepAliveSubscriptionQos( 80, // validity_ms 100, // minInterval_ms 200, // maxInterval_ms 80 // alertInterval_ms )); QString subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setAttributeName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( proxyParticipantId, providerParticipantId, qos, subscriptionRequest); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); dispatcher.receive(msg, qos); // Wait for a call to be made to the mockRequestCaller ASSERT_TRUE(semaphore.tryAcquire(1,1000)); }
/** * Trigger: The dispatcher receives a SubscriptionRequest. * Expected: The PublicationManager creates a PublisherRunnable and polls * the MockCaller for the attribute. */ TEST_F(SubscriptionTest, receive_subscriptionRequestAndPollAttribute) { // Use a semaphore to count and wait on calls to the mockRequestCaller Semaphore semaphore(0); EXPECT_CALL(*mockRequestCaller, getLocation(_,_)) .WillRepeatedly( DoAll( Invoke(mockRequestCaller.get(), &MockTestRequestCaller::invokeLocationOnSuccessFct), ReleaseSemaphore(&semaphore))); std::string attributeName = "Location"; Variant subscriptionQos = Variant::make<OnChangeWithKeepAliveSubscriptionQos>(OnChangeWithKeepAliveSubscriptionQos( 500, // validity_ms 1000, // minInterval_ms 2000, // maxInterval_ms 1000 // alertInterval_ms )); std::string subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setSubscribeToName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( proxyParticipantId, providerParticipantId, qos, subscriptionRequest); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); dispatcher.receive(msg); // Wait for a call to be made to the mockRequestCaller ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(1))); }
bool ControlPoint::subscribe(Service *service, long timeout) { if (service->isSubscribed() == true) { const char *sid = service->getSID(); return subscribe(service, sid, timeout); } Device *rootDev = service->getRootDevice(); if (rootDev == NULL) return false; lock(); const char *ifAddress = rootDev->getInterfaceAddress(); SubscriptionRequest subReq; string callbackURLBuf; subReq.setSubscribeRequest(service, getEventSubCallbackURL(ifAddress, callbackURLBuf), timeout); if (Debug::isOn() == true) subReq.print(); SubscriptionResponse *subRes = subReq.post(); if (Debug::isOn() == true) subRes->print(); bool ret = false; if (subRes->isSuccessful() == true) { string sidBuf; service->setSID(subRes->getSID(sidBuf)); service->setTimeout(subRes->getTimeout()); ret = true; } else service->clearSID(); unlock(); return ret; }
/** * Trigger: The dispatcher receives a Publication. * Expected: The SubscriptionManager retrieves the correct SubscriptionCallback and the * Interpreter executes it correctly */ TEST_F(SubscriptionTest, receive_publication ) { qRegisterMetaType<SubscriptionPublication>("SubscriptionPublication"); // getType is used by the ReplyInterpreterFactory to create an interpreter for the reply // so this has to match with the type being passed to the dispatcher in the reply ON_CALL(*mockReplyCaller, getType()).WillByDefault(Return(QString("QtGpsLocation"))); // Use a semaphore to count and wait on calls to the mockSubscriptionListener QSemaphore semaphore(0); EXPECT_CALL(*mockSubscriptionListener, onReceive(A<const types::QtGpsLocation&>())) .WillRepeatedly(ReleaseSemaphore(&semaphore)); //register the subscription on the consumer side QString attributeName = "Location"; auto subscriptionQos = QSharedPointer<QtSubscriptionQos>(new QtOnChangeWithKeepAliveSubscriptionQos( 80, // validity_ms 100, // minInterval_ms 200, // maxInterval_ms 80 // alertInterval_ms )); SubscriptionRequest subscriptionRequest; //construct a reply containing a QtGpsLocation SubscriptionPublication subscriptionPublication; subscriptionPublication.setSubscriptionId(subscriptionRequest.getSubscriptionId()); QList<QVariant> response; response.append(QVariant::fromValue(types::QtGpsLocation::createQt(gpsLocation1))); subscriptionPublication.setResponse(response); QSharedPointer<SubscriptionCallback<types::QtGpsLocation>> subscriptionCallback( new SubscriptionCallback<types::QtGpsLocation>(mockSubscriptionListener)); // subscriptionRequest is an out param subscriptionManager->registerSubscription( attributeName, subscriptionCallback, subscriptionQos, subscriptionRequest); // incoming publication from the provider JoynrMessage msg = messageFactory.createSubscriptionPublication( QString::fromStdString(providerParticipantId), QString::fromStdString(proxyParticipantId), qos, subscriptionPublication); dispatcher.receive(msg); // Assert that only one subscription message is received by the subscription listener ASSERT_TRUE(semaphore.tryAcquire(1, 1000)); ASSERT_FALSE(semaphore.tryAcquire(1, 250)); }
/** * Precondition: A provider is registered and there is at least one subscription for it. * Trigger: A subscription stop message is received * Expected: The PublicationManager stops the publications for this provider */ TEST_F(SubscriptionTest, stopMessage_stopsPublications) { qRegisterMetaType<QtOnChangeWithKeepAliveSubscriptionQos>("QtOnChangeWithKeepAliveSubscriptionQos"); qRegisterMetaType<SubscriptionRequest>("SubscriptionRequest"); // Use a semaphore to count and wait on calls to the mockRequestCaller QSemaphore semaphore(0); EXPECT_CALL(*mockRequestCaller, getLocation(_)) .WillRepeatedly( DoAll( Invoke(mockRequestCaller.data(), &MockTestRequestCaller::invokeOnSuccessFct), ReleaseSemaphore(&semaphore))); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); QString attributeName = "Location"; auto subscriptionQos = QSharedPointer<QtSubscriptionQos>(new QtOnChangeWithKeepAliveSubscriptionQos( 1200, // validity_ms 10, // minInterval_ms 100, // maxInterval_ms 1100 // alertInterval_ms )); QString subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setSubscribeToName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( QString::fromStdString(proxyParticipantId), QString::fromStdString(providerParticipantId), qos, subscriptionRequest); // first received message with subscription request dispatcher.receive(msg); // wait for two requests from the subscription ASSERT_TRUE(semaphore.tryAcquire(2, 1000)); SubscriptionStop subscriptionStop; subscriptionStop.setSubscriptionId(subscriptionRequest.getSubscriptionId()); // receive a subscription stop message msg = messageFactory.createSubscriptionStop( QString::fromStdString(proxyParticipantId), QString::fromStdString(providerParticipantId), qos, subscriptionStop); dispatcher.receive(msg); // assert that less than 2 requests happen in the next 300 milliseconds ASSERT_FALSE(semaphore.tryAcquire(2, 300)); }
bool ControlPoint::unsubscribe(Service *service) { SubscriptionRequest subReq; subReq.setUnsubscribeRequest(service); if (Debug::isOn() == true) subReq.print(); SubscriptionResponse *subRes = subReq.post(); if (Debug::isOn() == true) subRes->print(); if (subRes->isSuccessful() == true) { service->clearSID(); return true; } return false; }
void * Service::proc (void *p_args) { ServiceContext *contextp = (ServiceContext *) p_args; ServiceInterestList *interests = contextp->_interests; Service *service = contextp->_service; // Create a reader SubscriptionRequest request; Path *path; path = request.add_path_list(); path->set_path(service->getName()); path->set_sample_frequency(5000); ClientContext context; std::multimap<grpc::string_ref, grpc::string_ref> server_metadata; std::multimap<grpc::string_ref, grpc::string_ref>::iterator metadata_itr; std::unique_ptr<ClientReader<OpenConfigData>> reader(service->stub_->telemetrySubscribe(&context, request)); // Get the subscription ID from the response // Wait for the initial meta data to come back reader->WaitForInitialMetadata(); server_metadata = context.GetServerInitialMetadata(); metadata_itr = server_metadata.find("init-response"); std::string tmp = metadata_itr->second.data(); // Use Textformat Printer APIs to convert to right format google::protobuf::TextFormat::Parser parser; SubscriptionReply reply; SubscriptionResponse *response; parser.ParseFromString(tmp, &reply); response = reply.mutable_response(); service->setSubscriptionId(response->subscription_id()); // Create the read channel OpenConfigData kv; while (reader->Read(&kv)) { for (int i = 0; i < kv.kv_size(); i++) { const KeyValue &kv_data = kv.kv(i); ServiceCallbackKeyValue key_value(kv_data.key(), kv_data.str_value()); for (ServiceInterestListIterator itr = interests->begin(); itr != interests->end(); itr++) { Element *element = (*itr)->_element; (*itr)->_cb(element, &key_value); } } } // We are done. return NULL; }
/** * Trigger: The dispatcher receives an enum Publication. * Expected: The SubscriptionManager retrieves the correct SubscriptionCallback and the * Interpreter executes it correctly */ TEST_F(SubscriptionTest, receive_enumPublication ) { // getType is used by the ReplyInterpreterFactory to create an interpreter for the reply // so this has to match with the type being passed to the dispatcher in the reply ON_CALL(*mockReplyCaller, getType()).WillByDefault(Return(std::string("TestEnum"))); // Use a semaphore to count and wait on calls to the mockTestEnumSubscriptionListener Semaphore semaphore(0); EXPECT_CALL(*mockTestEnumSubscriptionListener, onReceive(A<const joynr::tests::testTypes::TestEnum::Enum&>())) .WillRepeatedly(ReleaseSemaphore(&semaphore)); //register the subscription on the consumer side std::string attributeName = "testEnum"; Variant subscriptionQos = Variant::make<OnChangeWithKeepAliveSubscriptionQos>(OnChangeWithKeepAliveSubscriptionQos( 500, // validity_ms 1000, // minInterval_ms 2000, // maxInterval_ms 1000 // alertInterval_ms )); SubscriptionRequest subscriptionRequest; //construct a reply containing a GpsLocation SubscriptionPublication subscriptionPublication; subscriptionPublication.setSubscriptionId(subscriptionRequest.getSubscriptionId()); std::vector<Variant> response; response.push_back(Variant::make<joynr::tests::testTypes::TestEnum::Enum>(tests::testTypes::TestEnum::ZERO)); subscriptionPublication.setResponse(response); auto subscriptionCallback = std::make_shared<SubscriptionCallback<joynr::tests::testTypes::TestEnum::Enum>>(mockTestEnumSubscriptionListener); // subscriptionRequest is an out param subscriptionManager->registerSubscription( attributeName, subscriptionCallback, subscriptionQos, subscriptionRequest); // incoming publication from the provider JoynrMessage msg = messageFactory.createSubscriptionPublication( providerParticipantId, proxyParticipantId, qos, subscriptionPublication); dispatcher.receive(msg); // Assert that only one subscription message is received by the subscription listener ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(1))); ASSERT_FALSE(semaphore.waitFor(std::chrono::seconds(1))); }
TEST_F(JoynrMessageFactoryTest, createSubscriptionRequest){ auto subscriptionQos = QSharedPointer<SubscriptionQos>(new OnChangeSubscriptionQos()); SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(QString("subscriptionId")); subscriptionRequest.setAttributeName(QString("attributeName")); subscriptionRequest.setQos(subscriptionQos); JoynrMessage joynrMessage = messageFactory.createSubscriptionRequest( senderID, receiverID, qos, subscriptionRequest ); checkParticipantIDs(joynrMessage); EXPECT_QSTREQ(JoynrMessage::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REQUEST, joynrMessage.getType()); }
bool ControlPoint::subscribe(Service *service, const std::string &uuid, long timeout) { SubscriptionRequest subReq; subReq.setRenewRequest(service, uuid, timeout); if (Debug::isOn() == true) subReq.print(); SubscriptionResponse *subRes = subReq.post(); if (Debug::isOn() == true) subRes->print(); if (subRes->isSuccessful() == true) { string sidBuf; service->setSID(subRes->getSID(sidBuf)); service->setTimeout(subRes->getTimeout()); return true; } service->clearSID(); return false; }
void ClassDeserializerImpl<SubscriptionRequest>::deserialize( SubscriptionRequest& subscriptionRequest, IObject& o) { while (o.hasNextField()) { IField& field = o.nextField(); if (field.name() == "subscriptionId") { subscriptionRequest.setSubscriptionId(field.value()); } if (field.name() == "subscribedToName") { subscriptionRequest.setSubscribeToName(field.value()); } if (field.name() == "qos") { Variant qos = convertVariant(field.value()); subscriptionRequest.setQos(qos); } } }
/** * Precondition: Dispatcher receives a SubscriptionRequest for a not(yet) existing Provider. * Trigger: The provider is registered. * Expected: The PublicationManager registers the provider and notifies the PublicationManager * to restore waiting Subscriptions */ TEST_F(SubscriptionTest, receive_RestoresSubscription) { qRegisterMetaType<QtOnChangeWithKeepAliveSubscriptionQos>("QtOnChangeWithKeepAliveSubscriptionQos"); qRegisterMetaType<SubscriptionRequest>("SubscriptionRequest"); // Use a semaphore to count and wait on calls to the mockRequestCaller QSemaphore semaphore(0); EXPECT_CALL( *mockRequestCaller, getLocation(A<std::function<void(const types::Localisation::GpsLocation&)>>()) ) .WillOnce(DoAll( Invoke(mockRequestCaller.data(), &MockTestRequestCaller::invokeOnSuccessFct), ReleaseSemaphore(&semaphore) )); QString attributeName = "Location"; auto subscriptionQos = QSharedPointer<QtSubscriptionQos>(new QtOnChangeWithKeepAliveSubscriptionQos( 80, // validity_ms 100, // minInterval_ms 200, // maxInterval_ms 80 // alertInterval_ms )); QString subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setSubscribeToName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( QString::fromStdString(proxyParticipantId), QString::fromStdString(providerParticipantId), qos, subscriptionRequest); // first received message with subscription request dispatcher.receive(msg); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); ASSERT_TRUE(semaphore.tryAcquire(1,15000)); //Try to acquire a semaphore for up to 5 seconds. Acquireing the semaphore will only work, if the mockRequestCaller has been called //and will be much faster than waiting for 500ms to make sure it has been called }
/** * Precondition: Dispatcher receives a SubscriptionRequest for a not(yet) existing Provider. * Trigger: The provider is registered. * Expected: The PublicationManager registers the provider and notifies the PublicationManager * to restore waiting Subscriptions */ TEST_F(SubscriptionTest, receive_RestoresSubscription) { // Use a semaphore to count and wait on calls to the mockRequestCaller Semaphore semaphore(0); EXPECT_CALL( *mockRequestCaller, getLocation(A<std::function<void(const types::Localisation::GpsLocation&)>>(), A<std::function<void(const joynr::exceptions::ProviderRuntimeException&)>>()) ) .WillOnce(DoAll( Invoke(mockRequestCaller.get(), &MockTestRequestCaller::invokeLocationOnSuccessFct), ReleaseSemaphore(&semaphore) )); std::string attributeName = "Location"; Variant subscriptionQos = Variant::make<OnChangeWithKeepAliveSubscriptionQos>(OnChangeWithKeepAliveSubscriptionQos( 500, // validity_ms 1000, // minInterval_ms 2000, // maxInterval_ms 1000 // alertInterval_ms )); std::string subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setSubscribeToName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( proxyParticipantId, providerParticipantId, qos, subscriptionRequest); // first received message with subscription request dispatcher.receive(msg); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(15))); //Try to acquire a semaphore for up to 15 seconds. Acquireing the semaphore will only work, if the mockRequestCaller has been called //and will be much faster than waiting for 1s to make sure it has been called }
/** * Precondition: A provider is registered and there is at least one subscription for it. * Trigger: The request caller is removed from the dispatcher * Expected: The PublicationManager stops all subscriptions for this provider */ TEST_F(SubscriptionTest, removeRequestCaller_stopsPublications) { // Use a semaphore to count and wait on calls to the mockRequestCaller Semaphore semaphore(0); EXPECT_CALL(*mockRequestCaller, getLocation(_,_)) .WillRepeatedly( DoAll( Invoke(mockRequestCaller.get(), &MockTestRequestCaller::invokeLocationOnSuccessFct), ReleaseSemaphore(&semaphore))); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); Variant subscriptionQos = Variant::make<OnChangeWithKeepAliveSubscriptionQos>(OnChangeWithKeepAliveSubscriptionQos( 1200, // validity_ms 10, // minInterval_ms 100, // maxInterval_ms 1100 // alertInterval_ms )); std::string subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); std::string attributeName = "Location"; subscriptionRequest.setSubscribeToName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( proxyParticipantId, providerParticipantId, qos, subscriptionRequest); // first received message with subscription request dispatcher.receive(msg); // wait for two requests from the subscription ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(1))); ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(1))); // remove the request caller dispatcher.removeRequestCaller(providerParticipantId); // assert that less than 2 requests happen in the next 300 milliseconds semaphore.waitFor(std::chrono::milliseconds(300)); ASSERT_FALSE(semaphore.waitFor(std::chrono::milliseconds(300))); }
TEST_F(AgentConsolidatorTest, add_multiple) { AgentConsolidatorHandle *handle1, *handle2; SubscriptionRequest request; SubscriptionRequest system_accepted_request; telemetry::Path *path; // Build a request path = request.add_path_list(); path->set_path("firewall"); path = request.add_path_list(); path->set_path("port"); // Add it to the consolidator handle1 = cons->addRequest(61, &request, &system_accepted_request); EXPECT_TRUE(handle1 != NULL); for (int i = 0; i < request.path_list_size(); i++) { EXPECT_STREQ(request.path_list(i).path().c_str(), system_accepted_request.path_list(i).path().c_str()); } // Add it to the consolidator handle2 = cons->addRequest(62, &request, &system_accepted_request); EXPECT_TRUE(handle2 != NULL); // Only two system requests should have been created EXPECT_EQ(2, cons->getSystemRequestCount()); EXPECT_EQ(2, cons->getAddCount()); EXPECT_EQ(0, cons->getErrors()); // Remove it now cons->removeRequest(handle1); EXPECT_EQ(2, cons->getSystemRequestCount()); EXPECT_EQ(1, cons->getRemCount()); EXPECT_EQ(0, cons->getErrors()); cons->removeRequest(handle2); EXPECT_EQ(0, cons->getSystemRequestCount()); EXPECT_EQ(2, cons->getRemCount()); EXPECT_EQ(0, cons->getErrors()); }
/** * Precondition: Dispatcher receives a SubscriptionRequest for a not(yet) existing Provider. * Trigger: The provider is registered. * Expected: The PublicationManager registers the provider and notifies the PublicationManager * to restore waiting Subscriptions */ TEST_F(SubscriptionTest, receive_RestoresSubscription) { qRegisterMetaType<OnChangeWithKeepAliveSubscriptionQos>("OnChangeWithKeepAliveSubscriptionQos"); qRegisterMetaType<SubscriptionRequest>("SubscriptionRequest"); // Use a semaphore to count and wait on calls to the mockRequestCaller QSemaphore semaphore(0); EXPECT_CALL(*mockRequestCaller, getLocation(A<RequestStatus&>(), A<types::GpsLocation&>())) .WillOnce(DoAll( SetArgReferee<1>(gpsLocation1), ReleaseSemaphore(&semaphore)) ); QString attributeName = "Location"; auto subscriptionQos = QSharedPointer<SubscriptionQos>(new OnChangeWithKeepAliveSubscriptionQos( 80, // validity_ms 100, // minInterval_ms 200, // maxInterval_ms 80 // alertInterval_ms )); QString subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setAttributeName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( proxyParticipantId, providerParticipantId, qos, subscriptionRequest); // first received message with subscription request dispatcher.receive(msg, qos); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); ASSERT_TRUE(semaphore.tryAcquire(1,15000)); //Try to acquire a semaphore for up to 5 seconds. Acquireing the semaphore will only work, if the mockRequestCaller has been called //and will be much faster than waiting for 500ms to make sure it has been called }
/** * Precondition: A provider is registered and there is at least one subscription for it. * Trigger: The request caller is removed from the dispatcher * Expected: The PublicationManager stops all subscriptions for this provider */ TEST_F(SubscriptionTest, removeRequestCaller_stopsPublications) { qRegisterMetaType<OnChangeWithKeepAliveSubscriptionQos>("OnChangeWithKeepAliveSubscriptionQos"); qRegisterMetaType<SubscriptionRequest>("SubscriptionRequest"); qRegisterMetaType<SubscriptionStop>("SubscriptionStop"); // Use a semaphore to count and wait on calls to the mockRequestCaller QSemaphore semaphore(0); EXPECT_CALL(*mockRequestCaller, getLocation(_, _)) .WillRepeatedly(ReleaseSemaphore(&semaphore)); dispatcher.addRequestCaller(providerParticipantId, mockRequestCaller); QString attributeName = "Location"; auto subscriptionQos = QSharedPointer<SubscriptionQos>(new OnChangeWithKeepAliveSubscriptionQos( 1200, // validity_ms 10, // minInterval_ms 100, // maxInterval_ms 1100 // alertInterval_ms )); QString subscriptionId = "SubscriptionID"; SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setAttributeName(attributeName); subscriptionRequest.setQos(subscriptionQos); JoynrMessage msg = messageFactory.createSubscriptionRequest( proxyParticipantId, providerParticipantId, qos, subscriptionRequest); // first received message with subscription request dispatcher.receive(msg, qos); // wait for two requests from the subscription ASSERT_TRUE(semaphore.tryAcquire(2, 1000)); // remove the request caller dispatcher.removeRequestCaller(providerParticipantId); // assert that less than 2 requests happen in the next 300 milliseconds ASSERT_FALSE(semaphore.tryAcquire(2, 300)); }
TEST_F(SubscriptionTest, sendPublication_attributeWithSingleArrayParam) { std::string subscriptionId = "SubscriptionID"; Variant subscriptionQos = Variant::make<OnChangeSubscriptionQos>(OnChangeSubscriptionQos( 800, // validity_ms 0 // minInterval_ms )); // Use a semaphore to count and wait on calls to the mockRequestCaller Semaphore semaphore(0); SubscriptionRequest subscriptionRequest; subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setSubscribeToName("listOfStrings"); subscriptionRequest.setQos(subscriptionQos); EXPECT_CALL( *provider, getListOfStrings(A<std::function<void(const std::vector<std::string> &)>>(), A<std::function<void(const joynr::exceptions::ProviderRuntimeException&)>>()) ) .WillOnce(DoAll( Invoke(provider.get(), &MockTestProvider::invokeListOfStringsOnSuccess), ReleaseSemaphore(&semaphore) )); auto mockMessageRouter = std::make_shared<MockMessageRouter>(); JoynrMessageSender* joynrMessageSender = new JoynrMessageSender(mockMessageRouter); /* ensure the serialization succeeds and the first publication is send to the proxy */ EXPECT_CALL(*mockMessageRouter, route( AllOf( A<JoynrMessage>(), Property(&JoynrMessage::getHeaderFrom, Eq(providerParticipantId)), Property(&JoynrMessage::getHeaderTo, Eq(proxyParticipantId))), _ )); publicationManager->add( proxyParticipantId, providerParticipantId, requestCaller, subscriptionRequest, joynrMessageSender); ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(15))); std::vector<std::string> listOfStrings; listOfStrings.push_back("1"); listOfStrings.push_back("2"); /* ensure the value change leads to another publication */ Mock::VerifyAndClear(mockMessageRouter.get()); EXPECT_CALL(*mockMessageRouter, route( AllOf( A<JoynrMessage>(), Property(&JoynrMessage::getHeaderFrom, Eq(providerParticipantId)), Property(&JoynrMessage::getHeaderTo, Eq(proxyParticipantId))), _ )); provider->listOfStringsChanged(listOfStrings); delete joynrMessageSender; }
void SubscriptionManager::registerSubscription( const std::string& subscribeToName, std::shared_ptr<ISubscriptionCallback> subscriptionCaller, const Variant& qosVariant, SubscriptionRequest& subscriptionRequest) { // Register the subscription std::string subscriptionId = subscriptionRequest.getSubscriptionId(); JOYNR_LOG_DEBUG(logger, "Subscription registered. ID={}", subscriptionId); if (subscriptions.contains(subscriptionId)) { // pre-existing subscription: remove it first from the internal data structure unregisterSubscription(subscriptionId); } std::int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch()).count(); subscriptionRequest.setQos(qosVariant); const SubscriptionQos* qos = subscriptionRequest.getSubscriptionQosPtr(); if (qos->getExpiryDateMs() != SubscriptionQos::NO_EXPIRY_DATE() && qos->getExpiryDateMs() < now) { throw std::invalid_argument("Subscription ExpiryDate " + std::to_string(qos->getExpiryDateMs()) + " in the past. Now: " + std::to_string(now)); } auto subscription = std::make_shared<Subscription>(subscriptionCaller); subscriptions.insert(subscriptionId, subscription); { std::lock_guard<std::recursive_mutex> subscriptionLocker(subscription->mutex); if (SubscriptionUtil::getAlertInterval(qosVariant) > 0 && SubscriptionUtil::getPeriodicPublicationInterval(qosVariant) > 0) { JOYNR_LOG_DEBUG(logger, "Will notify if updates are missed."); std::int64_t alertAfterInterval = SubscriptionUtil::getAlertInterval(qosVariant); JoynrTimePoint expiryDate(std::chrono::milliseconds(qos->getExpiryDateMs())); if (qos->getExpiryDateMs() == SubscriptionQos::NO_EXPIRY_DATE()) { expiryDate = JoynrTimePoint( std::chrono::milliseconds(std::numeric_limits<std::int64_t>::max())); } std::int64_t periodicPublicationInterval = SubscriptionUtil::getPeriodicPublicationInterval(qosVariant); subscription->missedPublicationRunnableHandle = missedPublicationScheduler->schedule( new MissedPublicationRunnable(expiryDate, periodicPublicationInterval, subscriptionId, subscription, *this, alertAfterInterval), std::chrono::milliseconds(alertAfterInterval)); } else if (qos->getExpiryDateMs() != SubscriptionQos::NO_EXPIRY_DATE()) { std::int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch()).count(); subscription->subscriptionEndRunnableHandle = missedPublicationScheduler->schedule( new SubscriptionEndRunnable(subscriptionId, *this), std::chrono::milliseconds(qos->getExpiryDateMs() - now)); } } subscriptionRequest.setSubscriptionId(subscriptionId); subscriptionRequest.setSubscribeToName(subscribeToName); }