TEST_F(LocalCapabilitiesDirectoryTest, getCapabilitiesForParticipantIdDelegatesToCapabilitiesClient) {

    EXPECT_CALL(*capabilitiesClient, getCapabilitiesForParticipantId(dummyParticipantId1, _))
            .Times(1)
            .WillOnce(Invoke(this, &LocalCapabilitiesDirectoryTest::fakeGetCapabilitiesForParticipantIdWithThreeResults));

    localCapabilitiesDirectory->getCapabilities(dummyParticipantId1, callback, discoveryQos);
    QList<CapabilityEntry> capabilities = callback->getResults(TIMEOUT);

    EXPECT_EQ(3, capabilities.size());
    bool interfaceAddress1Found = false;
    bool interfaceAddress2Found = false;
    for (int i = 0; i < capabilities.size(); i++) {
        CapabilityEntry entry = capabilities.at(i);
        if ((entry.getDomain() == DOMAIN_1_NAME) && (entry.getInterfaceName() == INTERFACE_1_NAME)) {
            interfaceAddress1Found = true;
        } else if ((entry.getDomain() == DOMAIN_2_NAME) && (entry.getInterfaceName() == INTERFACE_2_NAME)) {
            interfaceAddress2Found = true;
        }
    }

    EXPECT_TRUE(interfaceAddress1Found);
    EXPECT_TRUE(interfaceAddress2Found);

}
TEST_F(LocalCapabilitiesDirectoryTest, getCapabilitiesForInterfaceAddressDelegatesToCapabilitiesClient) {
    //simulate global capability directory would store two entries.
    EXPECT_CALL(*capabilitiesClient, getCapabilitiesForInterfaceAddress(DOMAIN_1_NAME ,INTERFACE_1_NAME,_))
            .Times(1)
            .WillOnce(Invoke(this, &LocalCapabilitiesDirectoryTest::fakeGetCapabilitiesForInterfaceAddressWithResults));

    types::ProviderQosRequirements qos;
    localCapabilitiesDirectory->getCapabilities(DOMAIN_1_NAME ,INTERFACE_1_NAME, callback, discoveryQos, qos);
    QList<CapabilityEntry> capabilities = callback->getResults(TIMEOUT);


    EXPECT_EQ(2, capabilities.size());

    // check that the results contain the two channel ids
    bool firstParticipantIdFound = false;
    bool secondParticipantIdFound = false;
    for (int i = 0; i < capabilities.size(); i++) {
        CapabilityEntry entry = capabilities.at(i);
        EXPECT_QSTREQ(DOMAIN_1_NAME, entry.getDomain());
        EXPECT_QSTREQ(INTERFACE_1_NAME, entry.getInterfaceName());
        QString participantId = entry.getParticipantId();
        if (participantId == dummyParticipantId1) {
            firstParticipantIdFound = true;
        } else if (participantId == dummyParticipantId2) {
            secondParticipantIdFound = true;
        }
    }

    EXPECT_TRUE(firstParticipantIdFound);
    EXPECT_TRUE(secondParticipantIdFound);
}
void DbusCapabilitiesUtil::copyDbusCapaEntryToJoynr(const joynr::messaging::types::Types::CapabilityEntry& dbusEntry, CapabilityEntry& joynrEntry) {
    joynrEntry.setInterfaceName(QString::fromStdString(dbusEntry.interfaceName));
    joynrEntry.setDomain(QString::fromStdString(dbusEntry.domain));
    joynrEntry.setParticipantId(QString::fromStdString(dbusEntry.participantId));

    // copy qos
    types::ProviderQos qos;
    copyDbusProviderQosToJoynr(dbusEntry.qos, qos);
    joynrEntry.setQos(qos);

    // copy addressess
    // at the moment only joynr messaging endpoint addresses are supported
    QList<QSharedPointer<joynr::system::Address>> endPointAddrList;
    copyDbusEndPointListToJoynr(dbusEntry.endpointAdresses, endPointAddrList);
    joynrEntry.setEndpointAddresses(endPointAddrList);
}
TEST_F(CapabilitiesAggregatorTest, lookup_byInterface_addsInProcessAddress){
    EXPECT_CALL(*mockDispatcher, containsRequestCaller(participantId))
            .Times(1)
            .WillOnce(Return(true));
    EXPECT_CALL(*mockDispatcher, lookupRequestCaller(participantId))
            .Times(1)
            .WillOnce(Return(requestCaller));
    EXPECT_CALL(*mockCapabilitiesStub, lookup(domain, interfaceName, _, _))
            .Times(1)
            .WillOnce(Return(mockLookupResults));

    QList<CapabilityEntry> results = capAggregator->lookup(domain, interfaceName, types::ProviderQosRequirements(), discoveryQos);
    ASSERT_EQ(1, results.size());
    CapabilityEntry firstEntry = results.first();
    ASSERT_EQ(1, firstEntry.getEndpointAddresses().size());
    QSharedPointer<joynr::system::Address> firstAddress = firstEntry.getEndpointAddresses().first();
    ASSERT_STREQ(InProcessEndpointAddress::ENDPOINTADDRESSTYPE.toLatin1(), firstAddress->metaObject()->className());
    QSharedPointer<InProcessEndpointAddress> inProcessAddress = firstAddress.dynamicCast<InProcessEndpointAddress>();
    EXPECT_EQ(requestCaller, inProcessAddress->getRequestCaller());
}
TEST_F(CapabilitiesAggregatorTest, async_lookup_byId_addsInProcessAddress){
    EXPECT_CALL(*mockDispatcher, containsRequestCaller(participantId))
            .Times(1)
            .WillOnce(Return(true));
    EXPECT_CALL(*mockDispatcher, lookupRequestCaller(participantId))
            .Times(1)
            .WillOnce(Return(requestCaller));
    EXPECT_CALL(*mockCapabilitiesStub, lookup(participantId, _))
            .Times(1)
            .WillOnce(InvokeWithoutArgs(this, &CapabilitiesAggregatorTest::fakeLookupBlocking));

    QSharedPointer<MockLocalCapabilitiesDirectoryCallback> callback(new MockLocalCapabilitiesDirectoryCallback());
    capAggregator->lookup(participantId, discoveryQos, callback);
    QList<CapabilityEntry> results(callback->getResults(3000));

    ASSERT_EQ(1, results.size());
    CapabilityEntry firstEntry = results.first();
    ASSERT_EQ(1, firstEntry.getEndpointAddresses().size());
    QSharedPointer<joynr::system::Address> firstAddress = firstEntry.getEndpointAddresses().first();
    ASSERT_STREQ(InProcessEndpointAddress::ENDPOINTADDRESSTYPE.toLatin1(), firstAddress->metaObject()->className());
    QSharedPointer<InProcessEndpointAddress> inProcessAddress = firstAddress.dynamicCast<InProcessEndpointAddress>();
    EXPECT_EQ(requestCaller, inProcessAddress->getRequestCaller());
}
void LocalCapabilitiesDirectory::remove(const std::string& domain,
                                        const std::string& interfaceName,
                                        const types::ProviderQos& qos)
{
    // TODO does it make sense to remove any capability for a domain/interfaceName
    // without knowing which provider registered the capability
    QMutexLocker locker(cacheLock);
    QList<CapabilityEntry> entries = interfaceAddress2GlobalCapabilities.lookUpAll(InterfaceAddress(
                                         QString::fromStdString(domain), QString::fromStdString(interfaceName)));
    std::vector<std::string> participantIdsToRemove;

    types::DiscoveryEntry discoveryEntry;

    for (int i = 0; i < entries.size(); ++i) {
        CapabilityEntry entry = entries.at(i);
        if (entry.isGlobal()) {
            types::CapabilityInformation capInfo(domain,
                                                 interfaceName,
                                                 qos,
                                                 capabilitiesClient->getLocalChannelId(),
                                                 entry.getParticipantId().toStdString());
            while (registeredGlobalCapabilities.erase(
                        std::remove(registeredGlobalCapabilities.begin(),
                                    registeredGlobalCapabilities.end(),
                                    capInfo),
                        registeredGlobalCapabilities.end()) !=
                    registeredGlobalCapabilities.end()) {
            }
            participantIdsToRemove.push_back(entry.getParticipantId().toStdString());
            participantId2GlobalCapabilities.remove(entry.getParticipantId(), entry);
            interfaceAddress2GlobalCapabilities.remove(
                InterfaceAddress(entry.getDomain(), entry.getInterfaceName()), entry);
        }
        participantId2LocalCapability.remove(entry.getParticipantId(), entry);
        interfaceAddress2LocalCapabilities.remove(
            InterfaceAddress(
                QString::fromStdString(domain), QString::fromStdString(interfaceName)),
            entry);

        convertCapabilityEntryIntoDiscoveryEntry(entry, discoveryEntry);
        informObserversOnRemove(discoveryEntry);
    }
    if (!participantIdsToRemove.empty()) {
        capabilitiesClient->remove(participantIdsToRemove);
    }
}
void DbusCapabilitiesUtil::copyJoynrCapaEntryToDbus(const CapabilityEntry& joynrEntry, joynr::messaging::types::Types::CapabilityEntry& dbusEntry) {
    dbusEntry.interfaceName = joynrEntry.getInterfaceName().toStdString();
    dbusEntry.domain = joynrEntry.getDomain().toStdString();
    dbusEntry.participantId = joynrEntry.getParticipantId().toStdString();
    dbusEntry.global = joynrEntry.isGlobal();

    // copy qos
    joynr::messaging::types::Types::ProviderQos qos;
    copyJoynrProviderQosToDbus(joynrEntry.getQos(), qos);
    dbusEntry.qos = qos;

    // at the moment only joynr messaging endpoint addresses are supported
    copyJoynrEndPointListToDbus(joynrEntry.getEndpointAddresses(), dbusEntry.endpointAdresses);
}
void LocalCapabilitiesDirectory::remove(const std::string& participantId)
{
    QMutexLocker lock(cacheLock);
    CapabilityEntry entry =
        participantId2LocalCapability.take(QString::fromStdString(participantId));
    interfaceAddress2LocalCapabilities.remove(
        InterfaceAddress(entry.getDomain(), entry.getInterfaceName()), entry);
    if (entry.isGlobal()) {
        participantId2GlobalCapabilities.remove(QString::fromStdString(participantId), entry);
        interfaceAddress2GlobalCapabilities.remove(
            InterfaceAddress(entry.getDomain(), entry.getInterfaceName()), entry);
    }

    types::DiscoveryEntry discoveryEntry;
    convertCapabilityEntryIntoDiscoveryEntry(entry, discoveryEntry);
    informObserversOnRemove(discoveryEntry);

    capabilitiesClient->remove(participantId);
}