bundles/remote_services/discovery_zeroconf/gtest/src/DiscoveryZeroconfWatcherTestSuite.cc (1,017 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "discovery_zeroconf_watcher.h" #include "discovery_zeroconf_constants.h" #include "remote_service_admin.h" #include "endpoint_listener.h" #include "remote_constants.h" #include "celix_threads_ei.h" #include "celix_bundle_context_ei.h" #include "celix_string_hash_map_ei.h" #include "celix_long_hash_map_ei.h" #include "celix_properties_ei.h" #include "celix_utils_ei.h" #include "mdnsresponder_ei.h" #include "malloc_ei.h" #include "celix_framework.h" #include "celix_framework_factory.h" #include "celix_log_helper.h" #include "celix_properties.h" #include "celix_constants.h" #include "celix_errno.h" #include "celix_log_service.h" #include "celix_log_utils.h" #include "celix_log_constants.h" #include <dns_sd.h> #include <netinet/in.h> #include <semaphore.h> #include <ctime> #include <cstdlib> #include <gtest/gtest.h> #include <ifaddrs.h> #include <netdb.h> #include <net/if.h> #define DZC_TEST_CONFIG_TYPE "celix.config_type.test" #define DZC_TEST_SERVICE_TYPE DZC_SERVICE_PRIMARY_TYPE",test" //use the last word of config type as service subtype #define DZC_TEST_SERVICE_PORT 60001 static const char *DZC_TEST_ENDPOINT_FW_UUID = "61EC83D5-A808-DA12-3615-B68376C35357"; static void OnDNSServiceRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *instanceName, const char *serviceType, const char *domain, void *data); static DNSServiceRef RegisterTestService(int ifIndex = kDNSServiceInterfaceIndexLocalOnly, const char *endpointId = "60f49d89-d105-430c-b12b-93fbb54b1d19", const char *serviceId = "100"); static const char *expectErrMsg = nullptr; static sem_t msgSyncSem; static void vlogDetails(void *handle, celix_log_level_e level, const char* file, const char* function, int line, const char* format, va_list formatArgs) { (void)handle; if (expectErrMsg != nullptr && strcmp(expectErrMsg, format) == 0) { sem_post(&msgSyncSem); } celix_logUtils_vLogToStdoutDetails("DiscoveryZeroconf", level, file, function, line, format, formatArgs); } static void ExpectMsgOutPut(const char *msg) { expectErrMsg = msg; } static bool CheckMsgWithTimeOutInS(int secs) { struct timespec ts{}; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += secs; errno = 0; while ((sem_timedwait(&msgSyncSem, &ts)) == -1 && errno == EINTR) continue; return errno == ETIMEDOUT; } static celix_status_t discoveryZeroconfWatcherTest_endpointAdded(void *handle, endpoint_description_t *endpoint, char *matchedFilter) { auto logHelper = static_cast<celix_log_helper_t*>(handle); (void)matchedFilter; EXPECT_STREQ("dzc_test_service", endpoint->serviceName); celix_logHelper_info(logHelper, "Endpoint added: %s.", endpoint->id); return CELIX_SUCCESS; } static celix_status_t discoveryZeroconfWatcherTest_endpointRemoved(void *handle, endpoint_description_t *endpoint, char *matchedFilter) { auto logHelper = static_cast<celix_log_helper_t*>(handle); (void)endpoint; (void)matchedFilter; celix_logHelper_info(logHelper, "Endpoint removed: %s.", endpoint->id); return CELIX_SUCCESS; } static int GetTestNetInterfaceIndex() { int ifIndex = 0; struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) != -1) { for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { if (ifa->ifa_addr == nullptr) continue; ifIndex = (int)if_nametoindex(ifa->ifa_name);// use non-loopback interface first, if not exist, use loopback interface if (!(ifa->ifa_flags & IFF_LOOPBACK)) { break; } } freeifaddrs(ifaddr); } return ifIndex; } class DiscoveryZeroconfWatcherTestSuite : public ::testing::Test { public: static void SetUpTestCase() { (void)system("sudo " MDNSD); } static void TearDownTestCase() { (void)system("sudo kill -s 9 `ps -aux | grep mdnsd | awk '{print $2}'`"); } DiscoveryZeroconfWatcherTestSuite() { auto* props = celix_properties_create(); celix_properties_set(props, CELIX_FRAMEWORK_CLEAN_CACHE_DIR_ON_CREATE, "true"); celix_properties_set(props, CELIX_FRAMEWORK_CACHE_DIR, ".dzc_watcher_test_cache"); celix_properties_set(props, CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL_CONFIG_NAME, "trace"); auto* fwPtr = celix_frameworkFactory_createFramework(props); auto* ctxPtr = celix_framework_getFrameworkContext(fwPtr); fw = std::shared_ptr<celix_framework_t>{fwPtr, [](auto* f) {celix_frameworkFactory_destroyFramework(f);}}; ctx = std::shared_ptr<celix_bundle_context_t>{ctxPtr, [](auto*){/*nop*/}}; auto* logHelperPtr = celix_logHelper_create(ctxPtr,"DiscoveryZeroconf"); logHelper = std::shared_ptr<celix_log_helper_t>{logHelperPtr, [](auto*l){ celix_logHelper_destroy(l);}}; epListener.handle = logHelperPtr; eplId = celix_bundleContext_registerService(ctxPtr, &epListener, CELIX_RSA_ENDPOINT_LISTENER_SERVICE_NAME, nullptr); EXPECT_LE(0, eplId); auto rsaSvcProps = celix_properties_create(); celix_properties_set(rsaSvcProps, CELIX_RSA_REMOTE_CONFIGS_SUPPORTED, DZC_TEST_CONFIG_TYPE); rsaSvcId = celix_bundleContext_registerService(ctx.get(), (void*)"dummy_service", CELIX_RSA_REMOTE_SERVICE_ADMIN, rsaSvcProps); EXPECT_LE(0, rsaSvcId); logService.handle = nullptr; logService.vlogDetails = vlogDetails; celix_service_registration_options_t opts{}; opts.svc = &logService; opts.serviceName = CELIX_LOG_SERVICE_NAME; opts.serviceVersion = CELIX_LOG_SERVICE_VERSION; opts.properties = celix_properties_create(); celix_properties_set(opts.properties, CELIX_LOG_SERVICE_PROPERTY_NAME, "DiscoveryZeroconf"); lsId = celix_bundleContext_registerServiceWithOptions(ctxPtr, &opts); EXPECT_LE(0, lsId); sem_init(&msgSyncSem, 0, 0); } ~DiscoveryZeroconfWatcherTestSuite() override { celix_ei_expect_celix_bundleContext_getProperty(nullptr, 0, nullptr); celix_ei_expect_celixThreadMutex_create(nullptr, 0, 0); celix_ei_expect_celix_bundleContext_trackServicesWithOptionsAsync(nullptr, 0, 0); celix_ei_expect_celixThread_create(nullptr, 0, 0); celix_ei_expect_DNSServiceCreateConnection(nullptr, 0, 0); celix_ei_expect_DNSServiceBrowse(nullptr, 0, 0); celix_ei_expect_DNSServiceProcessResult(nullptr, 0, 0); celix_ei_expect_DNSServiceResolve(nullptr, 0, 0, 0); celix_ei_expect_DNSServiceGetAddrInfo(nullptr, 0, 0, 0); celix_ei_expect_calloc(nullptr, 0, nullptr); celix_ei_expect_celix_stringHashMap_create(nullptr, 0, nullptr); celix_ei_expect_celix_stringHashMap_createWithOptions(nullptr, 0, nullptr); celix_ei_expect_celix_longHashMap_create(nullptr, 0, nullptr); celix_ei_expect_celix_properties_copy(nullptr, 0, nullptr); celix_ei_expect_celix_utils_strdup(nullptr, 0, nullptr); celix_ei_expect_celix_stringHashMap_put(nullptr, 0, 0); celix_ei_expect_celix_longHashMap_put(nullptr, 0, 0); sem_destroy(&msgSyncSem); celix_bundleContext_unregisterService(ctx.get(), lsId); celix_bundleContext_unregisterService(ctx.get(), rsaSvcId); celix_bundleContext_unregisterService(ctx.get(), eplId); } long TrackRsaService(discovery_zeroconf_watcher_t *watcher) { celix_service_tracking_options_t opts{}; opts.filter.serviceName = CELIX_RSA_REMOTE_SERVICE_ADMIN; opts.filter.filter = "(remote.configs.supported=*)"; opts.callbackHandle = watcher; opts.addWithProperties = [](void *handle, void *svc, const celix_properties_t *props) { discoveryZeroConfWatcher_addRSA(handle, svc, props); }; opts.removeWithProperties = [](void *handle, void *svc, const celix_properties_t *props) { discoveryZeroConfWatcher_removeRSA(handle, svc, props); }; auto id = celix_bundleContext_trackServicesWithOptions(ctx.get(), &opts); EXPECT_GT(id, 0); return id; } long TrackEndpointListenerService(discovery_zeroconf_watcher_t *watcher) { celix_service_tracking_options_t opts{}; opts.filter.serviceName = CELIX_RSA_ENDPOINT_LISTENER_SERVICE_NAME; opts.callbackHandle = watcher; opts.addWithProperties = [](void *handle, void *svc, const celix_properties_t *props) { discoveryZeroconfWatcher_addEPL(handle, svc, props); }; opts.removeWithProperties = [](void *handle, void *svc, const celix_properties_t *props) { discoveryZeroconfWatcher_removeEPL(handle, svc, props); }; auto id = celix_bundleContext_trackServicesWithOptions(ctx.get(), &opts); EXPECT_GT(id, 0); return id; } void TestRsaServiceAddAndRemove(void (*beforeAddRsaAction)(void), void (*afterAddRsaAction)(void), void (*beforeRemoveRsaAction)(void) = nullptr, void (*afterRemoveRsaAction)(void) = nullptr, const char *remoteConfigsSupported = DZC_TEST_CONFIG_TYPE) { celix_bundleContext_unregisterService(ctx.get(), rsaSvcId);//reset rsa service rsaSvcId = -1; discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); beforeAddRsaAction(); auto rsaSvcProps = celix_properties_create(); celix_properties_set(rsaSvcProps, CELIX_RSA_REMOTE_CONFIGS_SUPPORTED, remoteConfigsSupported); auto rsaId = celix_bundleContext_registerService(ctx.get(), (void*)"dummy_service", CELIX_RSA_REMOTE_SERVICE_ADMIN, rsaSvcProps); EXPECT_LE(0, rsaId); auto trkId = TrackRsaService(watcher); afterAddRsaAction(); if (beforeRemoveRsaAction != nullptr) { beforeRemoveRsaAction(); } celix_bundleContext_stopTracker(ctx.get(), trkId); celix_bundleContext_unregisterService(ctx.get(), rsaId); if (afterRemoveRsaAction != nullptr) { afterRemoveRsaAction(); } discoveryZeroconfWatcher_destroy(watcher); } void TestAddEndpoint(void (*beforeAddEndpoint)(void), void (*afterAddEndpoint)(void), int ifIndex = kDNSServiceInterfaceIndexLocalOnly) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto eplTrkId = TrackEndpointListenerService(watcher); beforeAddEndpoint(); auto rsaTrkId = TrackRsaService(watcher); auto dsRef = RegisterTestService(ifIndex); afterAddEndpoint(); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } void TestInvalidTxtRecord(void (*beforeAddTxt)(TXTRecordRef *txtRecord), void (*afterAddTxt)(void)) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); char txtBuf[1300] = {0}; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, sizeof(txtBuf), txtBuf); beforeAddTxt(&txtRecord); char propSizeStr[16]= {0}; sprintf(propSizeStr, "%d", TXTRecordGetCount(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord)) + 1); TXTRecordSetValue(&txtRecord, DZC_SERVICE_PROPERTIES_SIZE_KEY, strlen(propSizeStr), propSizeStr); DNSServiceRef dsRef{}; DNSServiceErrorType dnsErr; dnsErr = DNSServiceRegister(&dsRef, 0, kDNSServiceInterfaceIndexLocalOnly, "dzc_test_service", DZC_TEST_SERVICE_TYPE, "local", nullptr, htons(DZC_TEST_SERVICE_PORT), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), OnDNSServiceRegisterCallback, nullptr); EXPECT_EQ(dnsErr, kDNSServiceErr_NoError); DNSServiceProcessResult(dsRef); afterAddTxt(); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } void TestGetAddrInfo(void (*beforeRegServiceAction)(void), void (*afterRegServiceAction)(void)) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto eplTrkId = TrackEndpointListenerService(watcher); beforeRegServiceAction(); DNSServiceRef dsRef = RegisterTestService(kDNSServiceInterfaceIndexAny); afterRegServiceAction(); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } std::shared_ptr<celix_framework_t> fw{}; std::shared_ptr<celix_bundle_context_t> ctx{}; std::shared_ptr<celix_log_helper_t> logHelper{}; endpoint_listener_t epListener{nullptr,discoveryZeroconfWatcherTest_endpointAdded, discoveryZeroconfWatcherTest_endpointRemoved}; celix_log_service_t logService{}; long eplId{-1}; long lsId{-1}; long rsaSvcId{-1}; }; class DiscoveryZeroconfWatcherWatchServiceTestSuite : public DiscoveryZeroconfWatcherTestSuite { public: static void SetUpTestCase() { (void)system("sudo " MDNSD); sleep(3);//wait for mdnsd start testServiceRef = RegisterTestService(GetTestNetInterfaceIndex()); EXPECT_TRUE(testServiceRef != nullptr); } static void TearDownTestCase() { DNSServiceRefDeallocate(testServiceRef); (void)system("sudo kill -s 9 `ps -aux | grep mdnsd | awk '{print $2}'`"); } DiscoveryZeroconfWatcherWatchServiceTestSuite() { discovery_zeroconf_watcher_t *watcherPtr{}; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcherPtr); EXPECT_EQ(CELIX_SUCCESS, status); (void)GetTestNetInterfaceIndex; watcher = std::shared_ptr<discovery_zeroconf_watcher_t>{watcherPtr, [](auto w){discoveryZeroconfWatcher_destroy(w);}}; } ~DiscoveryZeroconfWatcherWatchServiceTestSuite() override = default; void TestWatchService(void (*beforeWatchServiceAction)(void), void (*afterWatchServiceAction)(void)) { beforeWatchServiceAction(); auto eplTrkId = TrackEndpointListenerService(watcher.get()); auto rsaTrkId = TrackRsaService(watcher.get()); afterWatchServiceAction(); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); } std::shared_ptr<discovery_zeroconf_watcher_t> watcher{}; static DNSServiceRef testServiceRef; }; DNSServiceRef DiscoveryZeroconfWatcherWatchServiceTestSuite::testServiceRef{nullptr}; TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateAndDestroyWatcher) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, Cleanup) { celix_autoptr(discovery_zeroconf_watcher_t) watcher = nullptr; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, StealPointer) { celix_autoptr(discovery_zeroconf_watcher_t) watcher = nullptr; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); discoveryZeroconfWatcher_destroy(celix_steal_ptr(watcher)); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed1) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_bundleContext_getProperty((void*)&discoveryZeroconfWatcher_create, 0, nullptr); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_BUNDLE_EXCEPTION, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed2) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celixThreadMutex_create((void*)&discoveryZeroconfWatcher_create, 0, CELIX_ENOMEM); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed4) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celixThread_create((void*)&discoveryZeroconfWatcher_create, 0, CELIX_ENOMEM); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed5) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_calloc((void*)&discoveryZeroconfWatcher_create, 0, nullptr); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed6) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_stringHashMap_create((void*)&discoveryZeroconfWatcher_create, 0, nullptr); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed7) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_stringHashMap_createWithOptions((void*)&discoveryZeroconfWatcher_create, 0, nullptr); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed8) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_stringHashMap_create((void*)&discoveryZeroconfWatcher_create, 0, nullptr, 2); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed9) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_stringHashMap_create((void*)&discoveryZeroconfWatcher_create, 0, nullptr, 3); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed10) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_longHashMap_create((void*)&discoveryZeroconfWatcher_create, 0, nullptr); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_ENOMEM, status); } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddRsaServiceWithOutRemoteConfigsSupported) { TestRsaServiceAddAndRemove([](){ celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr); ExpectMsgOutPut("Watcher: Failed to dup remote configs supported."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }, [](){ celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr); ExpectMsgOutPut("Watcher: Failed to dup remote configs supported."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddRsaServiceWithInvalidRemoteConfigsSupported) { TestRsaServiceAddAndRemove([](){ ExpectMsgOutPut("Watcher: Invalid service type for %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }, nullptr, nullptr, "celix.config_type_last_word_lager_than_63-----------------------------"); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToAllocMemoryForBrowserEntry) { TestRsaServiceAddAndRemove([](){ celix_ei_expect_calloc(CELIX_EI_UNKNOWN_CALLER, 0, nullptr); ExpectMsgOutPut("Watcher: Failed to alloc service browser entry."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToCreateServiceMapForBrowserEntry) { celix_ei_expect_DNSServiceCreateConnection(CELIX_EI_UNKNOWN_CALLER, 0, kDNSServiceErr_Unknown); ExpectMsgOutPut("Watcher: Failed to create connection for DNS service, %d.");//it is used for sync work thread TestRsaServiceAddAndRemove([](){ auto timeOut = CheckMsgWithTimeOutInS(1);//wait for work thread run EXPECT_FALSE(timeOut); celix_ei_expect_celix_stringHashMap_create(CELIX_EI_UNKNOWN_CALLER, 0, nullptr); ExpectMsgOutPut("Watcher: Failed to create watched services map."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToCreateRelatedListenerMapForBrowserEntry) { TestRsaServiceAddAndRemove([](){ celix_ei_expect_celix_longHashMap_create(CELIX_EI_UNKNOWN_CALLER, 0, nullptr); ExpectMsgOutPut("Watcher: Failed to create related listeners map."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToPutRelatedListenerToMapForBrowserEntry) { TestRsaServiceAddAndRemove([](){ celix_ei_expect_celix_longHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, ENOMEM); ExpectMsgOutPut("Watcher: Failed to attach listener to service browser."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToPutRelatedListenerToExistedMapForBrowserEntry) { TestRsaServiceAddAndRemove([](){ celix_ei_expect_celix_longHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM, 2); ExpectMsgOutPut("Watcher: Failed to attach listener to existed service browser."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); },nullptr, nullptr, "celix.test1.http,celix.test2.http"); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToPutBrowserEntryToCache) { TestRsaServiceAddAndRemove([](){ celix_ei_expect_celix_stringHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM); ExpectMsgOutPut("Watcher: Failed to put service browser entry."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(1); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddRsaServiceWithNoNameSpaceConfigType) { TestRsaServiceAddAndRemove([](){}, [](){}, nullptr, nullptr, "config_type_without_namespace"); } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddRsaServiceWithMultiConfigTypes) { TestRsaServiceAddAndRemove([](){}, [](){}, nullptr, nullptr, "celix.test1.http,celix.test1.http-json,celix.test2.http,celix.test2.http-json"); } TEST_F(DiscoveryZeroconfWatcherTestSuite, RsaServiceWithoutServiceIdTest) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); celix_autoptr(celix_properties_t) props = celix_properties_create(); celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_NAME, CELIX_RSA_REMOTE_SERVICE_ADMIN); status = discoveryZeroConfWatcher_addRSA(watcher, (void*)"dummy_service", props); EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, status); status = discoveryZeroConfWatcher_removeRSA(watcher, (void*)"dummy_service", props); EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, status); discoveryZeroconfWatcher_destroy(watcher); } static void OnDNSServiceRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *instanceName, const char *serviceType, const char *domain, void *data) { (void)sdRef;//unused (void)data;//unused (void)flags;//unused (void)instanceName;//unused (void)serviceType;//unused (void)domain;//unused EXPECT_EQ(errorCode, kDNSServiceErr_NoError); return; } static DNSServiceRef RegisterTestService(int ifIndex, const char *endpointId, const char *serviceId) { char txtBuf[1300] = {0}; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, sizeof(txtBuf), txtBuf); TXTRecordSetValue(&txtRecord, DZC_TXT_RECORD_VERSION_KEY, sizeof(DZC_CURRENT_TXT_RECORD_VERSION)-1, DZC_CURRENT_TXT_RECORD_VERSION); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_FRAMEWORK_UUID, strlen(DZC_TEST_ENDPOINT_FW_UUID), DZC_TEST_ENDPOINT_FW_UUID); TXTRecordSetValue(&txtRecord, CELIX_FRAMEWORK_SERVICE_NAME, strlen("dzc_test_service"), "dzc_test_service"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_ID, strlen(endpointId), endpointId); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_SERVICE_ID, strlen(serviceId), serviceId); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED, strlen("true"), "true"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED_CONFIGS, sizeof(DZC_TEST_CONFIG_TYPE) - 1, DZC_TEST_CONFIG_TYPE); TXTRecordSetValue(&txtRecord, CELIX_RSA_IP_ADDRESSES, 0, nullptr); char propSizeStr[16]= {0}; sprintf(propSizeStr, "%d", TXTRecordGetCount(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord)) + 1); TXTRecordSetValue(&txtRecord, DZC_SERVICE_PROPERTIES_SIZE_KEY, strlen(propSizeStr), propSizeStr); DNSServiceRef dsRef{}; DNSServiceErrorType dnsErr; static int conflictCount = 0; conflictCount++;//avoid conflict char name[32]={0}; snprintf(name, sizeof(name), "dzc_test_service_%d", conflictCount); dnsErr = DNSServiceRegister(&dsRef, 0, ifIndex, name, DZC_TEST_SERVICE_TYPE, "local", nullptr, htons(DZC_TEST_SERVICE_PORT), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), OnDNSServiceRegisterCallback, nullptr); if (dnsErr == kDNSServiceErr_NoError) { DNSServiceProcessResult(dsRef); } return dsRef; } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddAndRemoveEndpoint) { TestAddEndpoint([](){ ExpectMsgOutPut("Endpoint added: %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToCopyEndpointProperties) { TestAddEndpoint([](){ celix_ei_expect_celix_properties_copy(CELIX_EI_UNKNOWN_CALLER, 0, nullptr); ExpectMsgOutPut("Watcher: Failed to copy endpoint properties."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToAllocMemoryForEndpointEntry) { TestAddEndpoint([](){ //first calloc:service_browser_entry_t; second calloc:watched_service_entry_t; third calloc: endpointDescription_create celix_ei_expect_calloc(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 4); ExpectMsgOutPut("Watcher: Failed to alloc endpoint entry."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToCopyHostNameForEndpointEntry) { TestAddEndpoint([](){ //celix_utils_strdup call: first:addRsa; second:OnServiceResolveCallback; third: endpointDescription_create celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 4); ExpectMsgOutPut("Watcher: Failed to dup hostname for endpoint %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToGetLocalHostIpAddressesWhenCreateEndpoint) { TestAddEndpoint([](){ celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 5); ExpectMsgOutPut("Watcher: Failed to create endpoint for %s. %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }, kDNSServiceInterfaceIndexLocalOnly); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToPutEndpointToCache) { celix_ei_expect_celix_stringHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM, 4); TestAddEndpoint([](){ ExpectMsgOutPut("Watcher: Failed to add endpoint for %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, InvalidEndpoint) { TestInvalidTxtRecord([](TXTRecordRef *txtRecord){ TXTRecordSetValue(txtRecord, DZC_TXT_RECORD_VERSION_KEY, sizeof(DZC_CURRENT_TXT_RECORD_VERSION)-1, DZC_CURRENT_TXT_RECORD_VERSION); TXTRecordSetValue(txtRecord, CELIX_RSA_ENDPOINT_ID, sizeof("65d17a8c-f31b-478c-b13e-da743c96ab51")-1, "65d17a8c-f31b-478c-b13e-da743c96ab51"); TXTRecordSetValue(txtRecord, CELIX_RSA_ENDPOINT_SERVICE_ID, sizeof("100")-1, "-1"); TXTRecordSetValue(txtRecord, CELIX_RSA_SERVICE_IMPORTED, sizeof("true")-1, "true"); TXTRecordSetValue(txtRecord, CELIX_RSA_SERVICE_IMPORTED_CONFIGS, sizeof(DZC_TEST_CONFIG_TYPE)-1, DZC_TEST_CONFIG_TYPE); //No endpoint framework uuid ExpectMsgOutPut("Watcher: Failed to create endpoint description. %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateDNSServiceConnectionFailedOnce) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_DNSServiceCreateConnection(CELIX_EI_UNKNOWN_CALLER, 0, kDNSServiceErr_Unknown); ExpectMsgOutPut("Watcher: Failed to create connection for DNS service, %d."); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto dsRef = RegisterTestService(); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, DNSServiceBrowseFailedOnce) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_DNSServiceBrowse(CELIX_EI_UNKNOWN_CALLER, 0, kDNSServiceErr_Unknown); ExpectMsgOutPut("Watcher: Failed to browse DNS service, %d."); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto dsRef = RegisterTestService(); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, BrowseServicesFailed1) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_stringHashMap_create(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 4); ExpectMsgOutPut("Watcher: Failed to create updated service browsers cache."); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, BrowseServicesFailed2) { discovery_zeroconf_watcher_t *watcher; celix_ei_expect_celix_stringHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM, 2); ExpectMsgOutPut("Watcher: Failed to put browse entry, %d."); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto dsRef = RegisterTestService(); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToDeleteServiceBrowser) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto eplTrkId = TrackEndpointListenerService(watcher); ExpectMsgOutPut("Endpoint added: %s."); auto dsRef = RegisterTestService(); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); celix_ei_expect_celix_stringHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM); ExpectMsgOutPut("Watcher: Failed to put browse entry, %d."); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToPutWatchedServiceToCache) { TestAddEndpoint([](){ celix_ei_expect_celix_stringHashMap_putLong(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM); ExpectMsgOutPut("Watcher: Failed to cache service instance name, %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToAllocMemoryForSvcEntry) { TestAddEndpoint([](){ celix_ei_expect_calloc(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 2);//first calloc:service_browser_entry_t ExpectMsgOutPut("Watcher: Failed to alloc service entry."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToCreateTxtRecordForSvcEntry) { TestAddEndpoint([](){ celix_ei_expect_celix_properties_create(CELIX_EI_UNKNOWN_CALLER, 0, nullptr); ExpectMsgOutPut("Watcher: Failed to create txt record for service entry."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToPutSvcEntryToCache) { celix_ei_expect_celix_stringHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM, 3); TestAddEndpoint([](){ ExpectMsgOutPut("Watcher: Failed to put service entry, %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToSetTxtRecordToSvcEntry) { TestAddEndpoint([](){ celix_ei_expect_celix_properties_set(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM); ExpectMsgOutPut("Watcher: Failed to set txt record item(%s), %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToDupHostNameForSvcEntry) { TestAddEndpoint([](){ celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 2); ExpectMsgOutPut("Watcher: Failed to dup hostname."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherTestSuite, UnregisterRsaWhenBrowseServices) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto eplTrkId = TrackEndpointListenerService(watcher); ExpectMsgOutPut("Endpoint added: %s."); auto dsRef = RegisterTestService(); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, DNSServiceResultProcessFailed1) { discovery_zeroconf_watcher_t *watcher; auto dsRef = RegisterTestService(); celix_ei_expect_DNSServiceProcessResult(CELIX_EI_UNKNOWN_CALLER, 0, kDNSServiceErr_ServiceNotRunning); ExpectMsgOutPut("Watcher: mDNS connection may be broken, %d."); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); DNSServiceRefDeallocate(dsRef); } TEST_F(DiscoveryZeroconfWatcherTestSuite, DNSServiceResultProcessFailed2) { discovery_zeroconf_watcher_t *watcher; auto dsRef = RegisterTestService(); celix_ei_expect_DNSServiceProcessResult(CELIX_EI_UNKNOWN_CALLER, 0, kDNSServiceErr_Unknown); ExpectMsgOutPut("Watcher: Failed to process mDNS result, %d."); celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); DNSServiceRefDeallocate(dsRef); } TEST_F(DiscoveryZeroconfWatcherTestSuite, DNSServiceResolveFailedOnce) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); celix_ei_expect_DNSServiceResolve(CELIX_EI_UNKNOWN_CALLER, 0, kDNSServiceErr_NoMemory); ExpectMsgOutPut("Watcher: Failed to resolve %s on %d, %d."); auto dsRef = RegisterTestService(); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddAndRemoveSelfFrameworkEndpoint) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); char txtBuf[1300] = {0}; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, sizeof(txtBuf), txtBuf); const char *fwUuid = celix_bundleContext_getProperty(ctx.get(), CELIX_FRAMEWORK_UUID, nullptr); TXTRecordSetValue(&txtRecord, DZC_TXT_RECORD_VERSION_KEY, sizeof(DZC_CURRENT_TXT_RECORD_VERSION)-1, DZC_CURRENT_TXT_RECORD_VERSION); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_FRAMEWORK_UUID, fwUuid == nullptr ? 0 : strlen(fwUuid), fwUuid); TXTRecordSetValue(&txtRecord, CELIX_FRAMEWORK_SERVICE_NAME, strlen("dzc_test_self_fw_service"), "dzc_test_self_fw_service"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_ID, strlen("60f49d89-d105-430c-b12b-93fbb54b1d19"), "60f49d89-d105-430c-b12b-93fbb54b1d19"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_SERVICE_ID, strlen("100"), "100"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED, strlen("true"), "true"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED_CONFIGS, sizeof(DZC_TEST_CONFIG_TYPE)-1, DZC_TEST_CONFIG_TYPE); char propSizeStr[16]= {0}; sprintf(propSizeStr, "%d", TXTRecordGetCount(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord)) + 1); TXTRecordSetValue(&txtRecord, DZC_SERVICE_PROPERTIES_SIZE_KEY, strlen(propSizeStr), propSizeStr); ExpectMsgOutPut("Watcher: Ignore self endpoint for %s."); DNSServiceRef dsRef{}; DNSServiceErrorType dnsErr = DNSServiceRegister(&dsRef, 0, kDNSServiceInterfaceIndexLocalOnly, "dzc_test_self_fw_service", DZC_TEST_SERVICE_TYPE, "local", nullptr, htons(DZC_PORT_DEFAULT), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), OnDNSServiceRegisterCallback,nullptr); EXPECT_EQ(dnsErr, kDNSServiceErr_NoError); DNSServiceProcessResult(dsRef); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddTxtRecord) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); auto eplTrkId = TrackEndpointListenerService(watcher); char txtBuf[1300] = {0}; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, sizeof(txtBuf), txtBuf); TXTRecordSetValue(&txtRecord, DZC_TXT_RECORD_VERSION_KEY, sizeof(DZC_CURRENT_TXT_RECORD_VERSION)-1, DZC_CURRENT_TXT_RECORD_VERSION); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_FRAMEWORK_UUID, strlen(DZC_TEST_ENDPOINT_FW_UUID), DZC_TEST_ENDPOINT_FW_UUID); TXTRecordSetValue(&txtRecord, CELIX_FRAMEWORK_SERVICE_NAME, strlen("dzc_test_service"), "dzc_test_service"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_ID, strlen("60f49d89-d105-430c-b12b-93fbb54b1d18"), "60f49d89-d105-430c-b12b-93fbb54b1d18"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_SERVICE_ID, strlen("100"), "100"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED, strlen("true"), "true"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED_CONFIGS, sizeof(DZC_TEST_CONFIG_TYPE)-1, DZC_TEST_CONFIG_TYPE); char propSizeStr[16]= {0}; sprintf(propSizeStr, "%d", TXTRecordGetCount(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord)) + 1 + 5); TXTRecordSetValue(&txtRecord, DZC_SERVICE_PROPERTIES_SIZE_KEY, strlen(propSizeStr), propSizeStr); ExpectMsgOutPut("Endpoint added: %s."); DNSServiceRef dsRef{}; DNSServiceErrorType dnsErr = DNSServiceRegister(&dsRef, 0, kDNSServiceInterfaceIndexAny, "dzc_test_service", DZC_TEST_SERVICE_TYPE, "local", nullptr, htons(DZC_PORT_DEFAULT), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), OnDNSServiceRegisterCallback, nullptr); EXPECT_EQ(dnsErr, kDNSServiceErr_NoError); DNSServiceProcessResult(dsRef); TXTRecordDeallocate(&txtRecord); //add more txt record TXTRecordCreate(&txtRecord, sizeof(txtBuf), txtBuf); for (int i = 0; i < 5; ++i) { char key[20]{}; sprintf(key,"custom_key%d", i); char val[10]{}; sprintf(val,"%d", i); TXTRecordSetValue(&txtRecord, key, strlen(val), val); } DNSRecordRef rdRef;//It will be free when deallocate dsRef dnsErr = DNSServiceAddRecord(dsRef, &rdRef, 0, kDNSServiceType_TXT, TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), 0); EXPECT_EQ(dnsErr, kDNSServiceErr_NoError); TXTRecordDeallocate(&txtRecord); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, AddAndRemoveEndpointListener) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto rsaTrkId = TrackRsaService(watcher); char txtBuf[1300] = {0}; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, sizeof(txtBuf), txtBuf); TXTRecordSetValue(&txtRecord, DZC_TXT_RECORD_VERSION_KEY, sizeof(DZC_CURRENT_TXT_RECORD_VERSION)-1, DZC_CURRENT_TXT_RECORD_VERSION); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_FRAMEWORK_UUID, strlen(DZC_TEST_ENDPOINT_FW_UUID), DZC_TEST_ENDPOINT_FW_UUID); TXTRecordSetValue(&txtRecord, CELIX_FRAMEWORK_SERVICE_NAME, strlen("dzc_test_service"), "dzc_test_service"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_ID, strlen("60f49d89-d105-430c-b12b-93fbb54b1d19"), "60f49d89-d105-430c-b12b-93fbb54b1d19"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_SERVICE_ID, strlen("100"), "100"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED, strlen("true"), "true"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED_CONFIGS, sizeof(DZC_TEST_CONFIG_TYPE)-1, DZC_TEST_CONFIG_TYPE); char propSizeStr[16]= {0}; sprintf(propSizeStr, "%d", TXTRecordGetCount(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord)) + 1); TXTRecordSetValue(&txtRecord, DZC_SERVICE_PROPERTIES_SIZE_KEY, strlen(propSizeStr), propSizeStr); DNSServiceRef dsRef{}; DNSServiceErrorType dnsErr = DNSServiceRegister(&dsRef, 0, kDNSServiceInterfaceIndexLocalOnly, "dzc_test_service", DZC_TEST_SERVICE_TYPE, "local", nullptr, htons(DZC_PORT_DEFAULT), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), OnDNSServiceRegisterCallback,nullptr); EXPECT_EQ(dnsErr, kDNSServiceErr_NoError); DNSServiceProcessResult(dsRef); ExpectMsgOutPut("Endpoint added: %s."); auto eplTrkId = TrackEndpointListenerService(watcher); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); ExpectMsgOutPut("Endpoint removed: %s."); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); DNSServiceRefDeallocate(dsRef); celix_bundleContext_stopTracker(ctx.get(), rsaTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, EndpointListenerSpesificServiceConfigTypeTest) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); auto props = celix_properties_create(); status = celix_properties_set(props, CELIX_RSA_ENDPOINT_LISTENER_SCOPE, "(" CELIX_RSA_SERVICE_IMPORTED_CONFIGS "=" DZC_TEST_CONFIG_TYPE ")"); EXPECT_EQ(CELIX_SUCCESS, status); long listenerId = celix_bundleContext_registerService(ctx.get(), &epListener, CELIX_RSA_ENDPOINT_LISTENER_SERVICE_NAME, props); EXPECT_LE(0, listenerId); char txtBuf[1300] = {0}; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, sizeof(txtBuf), txtBuf); TXTRecordSetValue(&txtRecord, DZC_TXT_RECORD_VERSION_KEY, sizeof(DZC_CURRENT_TXT_RECORD_VERSION)-1, DZC_CURRENT_TXT_RECORD_VERSION); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_FRAMEWORK_UUID, strlen(DZC_TEST_ENDPOINT_FW_UUID), DZC_TEST_ENDPOINT_FW_UUID); TXTRecordSetValue(&txtRecord, CELIX_FRAMEWORK_SERVICE_NAME, strlen("dzc_test_service"), "dzc_test_service"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_ID, strlen("60f49d89-d105-430c-b12b-93fbb54b1d19"), "60f49d89-d105-430c-b12b-93fbb54b1d19"); TXTRecordSetValue(&txtRecord, CELIX_RSA_ENDPOINT_SERVICE_ID, strlen("100"), "100"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED, strlen("true"), "true"); TXTRecordSetValue(&txtRecord, CELIX_RSA_SERVICE_IMPORTED_CONFIGS, sizeof(DZC_TEST_CONFIG_TYPE)-1, DZC_TEST_CONFIG_TYPE); char propSizeStr[16]= {0}; sprintf(propSizeStr, "%d", TXTRecordGetCount(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord)) + 1); TXTRecordSetValue(&txtRecord, DZC_SERVICE_PROPERTIES_SIZE_KEY, strlen(propSizeStr), propSizeStr); DNSServiceRef dsRef{}; DNSServiceErrorType dnsErr = DNSServiceRegister(&dsRef, 0, kDNSServiceInterfaceIndexLocalOnly, "dzc_test_service", DZC_TEST_SERVICE_TYPE, "local", nullptr, htons(DZC_PORT_DEFAULT), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), OnDNSServiceRegisterCallback,nullptr); EXPECT_EQ(dnsErr, kDNSServiceErr_NoError); DNSServiceProcessResult(dsRef); ExpectMsgOutPut("Endpoint added: %s."); auto eplTrkId = TrackEndpointListenerService(watcher); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); ExpectMsgOutPut("Endpoint removed: %s."); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); celix_bundleContext_unregisterService(ctx.get(), listenerId); DNSServiceRefDeallocate(dsRef); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, FailedToAllocMemoryForEPL) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); ExpectMsgOutPut("Watcher: Failed to alloc endpoint listener entry."); celix_ei_expect_calloc((void*)&discoveryZeroconfWatcher_addEPL, 0, nullptr); auto eplTrkId = TrackEndpointListenerService(watcher); auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); celix_bundleContext_stopTracker(ctx.get(), eplTrkId); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherTestSuite, EndpointListenerServiceWithoutServiceIdTest) { discovery_zeroconf_watcher_t *watcher; celix_status_t status = discoveryZeroconfWatcher_create(ctx.get(), logHelper.get(), &watcher); EXPECT_EQ(CELIX_SUCCESS, status); celix_autoptr(celix_properties_t) props = celix_properties_create(); celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_NAME, CELIX_RSA_ENDPOINT_LISTENER_SERVICE_NAME); status = discoveryZeroconfWatcher_addEPL(watcher, (void*)"dummy_service", props); EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, status); status = discoveryZeroconfWatcher_removeEPL(watcher, (void*)"dummy_service", props); EXPECT_EQ(CELIX_ILLEGAL_ARGUMENT, status); discoveryZeroconfWatcher_destroy(watcher); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, FailedToGetHostIpAddressesWhenCreateEndpoint) { TestWatchService([](){ celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 5); ExpectMsgOutPut("Watcher: Failed to create endpoint for %s. %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30000); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, DNSServiceGetAddrInfoFailedOnce) { TestWatchService([](){ celix_ei_expect_DNSServiceGetAddrInfo(CELIX_EI_UNKNOWN_CALLER, 0, kDNSServiceErr_NoMemory); ExpectMsgOutPut("Watcher: Failed to get address info for %s on %d, %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, FailedToAllocMemoryForHostEntry) { TestWatchService([](){ celix_ei_expect_calloc(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 4);//first calloc:watched_epl_entry_t; second calloc:service_browser_entry_t; third calloc:watched_service_entry_t ExpectMsgOutPut("Watcher: Failed to alloc host entry for %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, FailedToDupHostNameForHostEntry) { TestWatchService([](){ celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 3); ExpectMsgOutPut("Watcher: Failed to dup hostname for %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, FailedToPutHostEntryToCache) { TestWatchService([](){ celix_ei_expect_celix_stringHashMap_put(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM, 4); ExpectMsgOutPut("Watcher: Failed to add host entry for %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, GetAddrInfo) { TestWatchService([](){ ExpectMsgOutPut("Endpoint added: %s."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, FailedToPutIpToHostEntry) { TestWatchService([](){ celix_ei_expect_celix_stringHashMap_putBool(CELIX_EI_UNKNOWN_CALLER, 0, CELIX_ENOMEM); ExpectMsgOutPut("Watcher: Failed to add ip address(%s). %d."); }, [](){ auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); } TEST_F(DiscoveryZeroconfWatcherWatchServiceTestSuite, AddMultiEndpoint) { TestWatchService([](){ ExpectMsgOutPut("Endpoint added: %s."); }, [](){ //wait for endpoint1 added auto timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); //register service2 auto dsRef2 = RegisterTestService(kDNSServiceInterfaceIndexAny, "65d17a8c-f31b-478c-b13e-da743c96ab51", "101"); //wait for endpoint2 added timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); ExpectMsgOutPut("Endpoint removed: %s."); DNSServiceRefDeallocate(dsRef2); //wait for endpoint2 added timeOut = CheckMsgWithTimeOutInS(30); EXPECT_FALSE(timeOut); }); }