/** * 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)); }
/** * Trigger: The dispatcher receives a Publication from a broadcast with multiple output parameters. * Expected: The SubscriptionManager retrieves the correct SubscriptionCallback and the * Interpreter executes it correctly */ TEST_F(BroadcastSubscriptionTest, receive_publication_multipleOutputParameters ) { qRegisterMetaType<SubscriptionPublication>("SubscriptionPublication"); // Use a semaphore to count and wait on calls to the mockSubscriptionListener QSemaphore semaphore(0); EXPECT_CALL(*mockSubscriptionListenerTwo, onReceive(A<const types::QtGpsLocation&>(), A<const double&>())) .WillRepeatedly(ReleaseSemaphore(&semaphore)); //register the subscription on the consumer side QString subscribeToName = "locationUpdateWithSpeed"; auto subscriptionQos = QSharedPointer<QtOnChangeSubscriptionQos>(new QtOnChangeWithKeepAliveSubscriptionQos( 80, // validity_ms 100, // minInterval_ms 200, // maxInterval_ms 80 // alertInterval_ms )); BroadcastSubscriptionRequest subscriptionRequest; //construct a reply containing a QtGpsLocation SubscriptionPublication subscriptionPublication; subscriptionPublication.setSubscriptionId(subscriptionRequest.getSubscriptionId()); QList<QVariant> response; response.append(QVariant::fromValue(gpsLocation1)); response.append(QVariant::fromValue(speed1)); subscriptionPublication.setResponse(response); QSharedPointer<SubscriptionCallback<types::QtGpsLocation, double>> subscriptionCallback( new SubscriptionCallback<types::QtGpsLocation, double>(mockSubscriptionListenerTwo)); // subscriptionRequest is an out param subscriptionManager->registerSubscription( subscribeToName, 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.tryAcquire(1, 1000)); ASSERT_FALSE(semaphore.tryAcquire(1, 250)); }
/** * 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))); }
void Dispatcher::handlePublicationReceived(const JoynrMessage& message) { std::string jsonSubscriptionPublication = message.getPayload(); try { SubscriptionPublication subscriptionPublication = JsonSerializer::deserialize<SubscriptionPublication>(jsonSubscriptionPublication); std::string subscriptionId = subscriptionPublication.getSubscriptionId(); assert(subscriptionManager != nullptr); std::shared_ptr<ISubscriptionCallback> callback = subscriptionManager->getSubscriptionCallback(subscriptionId); if (!callback) { JOYNR_LOG_ERROR(logger, "Dropping reply for non/no more existing subscription with id = {}", subscriptionId); return; } subscriptionManager->touchSubscriptionState(subscriptionId); int typeId = callback->getTypeId(); // Get the publication interpreter - this has to be a reference to support // PublicationInterpreter polymorphism IPublicationInterpreter& interpreter = MetaTypeRegistrar::instance().getPublicationInterpreter(typeId); interpreter.execute(callback, subscriptionPublication); } catch (const std::invalid_argument& e) { JOYNR_LOG_ERROR( logger, "Unable to deserialize subscription publication object from: {} - error: {}", jsonSubscriptionPublication, e.what()); } }
void Dispatcher::handlePublicationReceived(const JoynrMessage& message) { QByteArray jsonSubscriptionPublication = message.getPayload(); SubscriptionPublication* subscriptionPublication = JsonSerializer::deserialize<SubscriptionPublication>(jsonSubscriptionPublication); if (subscriptionPublication == Q_NULLPTR) { LOG_ERROR(logger, QString("Unable to deserialize subscription publication object from: %1") .arg(QString::fromUtf8(jsonSubscriptionPublication))); return; } QString subscriptionId = subscriptionPublication->getSubscriptionId(); assert(subscriptionManager != NULL); QSharedPointer<ISubscriptionCallback> callback = subscriptionManager->getSubscriptionCallback(subscriptionId); if (callback.isNull()) { LOG_ERROR(logger, "Dropping reply for non/no more existing subscription with id=" + subscriptionId); delete subscriptionPublication; return; } subscriptionManager->touchSubscriptionState(subscriptionId); int typeId = callback->getTypeId(); // Get the publication interpreter - this has to be a reference to support // PublicationInterpreter polymorphism IPublicationInterpreter& interpreter = MetaTypeRegistrar::instance().getPublicationInterpreter(typeId); interpreter.execute(callback, *subscriptionPublication); delete subscriptionPublication; }
void InProcessPublicationSender::sendSubscriptionPublication( const std::string& senderParticipantId, const std::string& receiverParticipantId, const MessagingQos& qos, const SubscriptionPublication& subscriptionPublication) { Q_UNUSED(senderParticipantId); // interface has sourcePartId, because JoynrMessages have a // source and dest. partId. Those are not necessary for in // process Q_UNUSED(receiverParticipantId); Q_UNUSED(qos); /** * just call the InProcessDispatcher! */ QString subscriptionId = subscriptionPublication.getSubscriptionId(); LOG_TRACE(logger, "Sending publication. id=" + subscriptionId); assert(subscriptionManager != NULL); subscriptionManager->touchSubscriptionState(subscriptionId); QSharedPointer<ISubscriptionCallback> callback = subscriptionManager->getSubscriptionCallback(subscriptionId); if (callback.isNull()) { LOG_ERROR(logger, "Dropping reply for non/no more existing subscription with id=" + subscriptionId); return; } int typeId = callback->getTypeId(); // Get the publication interpreter - this has to be a reference to support // PublicationInterpreter polymorphism IPublicationInterpreter& interpreter = MetaTypeRegistrar::instance().getPublicationInterpreter(typeId); LOG_TRACE(logger, "Interpreting publication. id=" + subscriptionId); interpreter.execute(callback, subscriptionPublication); }