/* * (c) Copyright, Real-Time Innovations, 2023. * All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef ddsctesthelpers_testHelper_h #define ddsctesthelpers_testHelper_h #include "rtitest/test_setting.h" #include "dds_c/dds_c_typecode.h" #include "ndds/ndds_config_c.h" #include "ndds/ndds_transport_c.h" #include "dds_c/dds_c_publication.h" #include "dds_c/dds_c_subscription.h" #include "dds_c/dds_c_trust_plugins.h" #include "pres/pres_readerQueue.h" #include "commend/commend_readerService.h" #include "disc/disc_simple_discovery_plugin.h" #include "clock/clock_mock.h" /** * @mainpage DDS Test Helpers * @brief A set of functions that simplifies testing of Connext applications. */ /** * @defgroup DDSCTestHelpers DDS Test Helpers * @brief A set of functions that simplifies testing of Connext applications. */ #ifdef __cplusplus extern "C" { #endif #define DDSC_TESTER_DEFAULT_LIB "BuiltinQosLib" #define DDSC_TESTER_DEFAULT_PROFILE "Baseline" /* * RTI_OSAPI_THREAD_STACK_SIZE_DEFAULT is sufficient for internal threads such * as the event and receive threads, but sometimes you need to use * DDS_C_TEST_THREAD_STACK_SIZE_DEFAULT for threads that directly call DDS * APIs. */ #ifdef RTI_VXWORKS /* * This number comes from the "Core Libraries Getting Started Guide Addendum * for Embedded Systems", "Getting Started on VxWorks Systems" chapter, * "Building and Running a Hello World Example" section, "Building and * Running an Application as a Real-Time Process" subsection. */ #define DDS_C_TEST_THREAD_STACK_SIZE_DEFAULT (0x100000) #else #define DDS_C_TEST_THREAD_STACK_SIZE_DEFAULT \ RTI_OSAPI_THREAD_STACK_SIZE_DEFAULT #endif #define DDS_C_TEST_DSN_MAX_LENGTH 100 #define DDS_C_TEST_LIBNAME_MAX_LENGTH 255 #define DDS_C_TEST_MAX_TEST_DATABASES 10 #define DDS_C_TEST_HELPER_LOGGER_DEVICE_DATA_MAX_SUBSTRINGS 10 /* * PREDIX-283: With current configuration, we make sure we do not reuse * ports for the domains in range 0-199. We map the ports to the range * [55005-57004]. We are starting in 55005 so we avoid collisions with service * running on ubuntu on 55002. */ #define DDS_C_TEST_HELPER_MULTICHANNEL_RECEIVE_PORT_BASE 55005 #define DDS_C_TEST_HELPER_MULTICHANNEL_RECEIVE_PORT_RANGE 2000 #define DDS_C_TEST_HELPER_MULTICHANNEL_RECEIVE_PORT_RANGE_PER_DOMAIN 10 #define DDSCTestHelper_calculateReceivePort(domainId__, offset__) \ (DDS_C_TEST_HELPER_MULTICHANNEL_RECEIVE_PORT_BASE + (offset__) + \ ((DDS_C_TEST_HELPER_MULTICHANNEL_RECEIVE_PORT_RANGE_PER_DOMAIN * (domainId__)) \ % DDS_C_TEST_HELPER_MULTICHANNEL_RECEIVE_PORT_RANGE)) struct DDSCTesterHelperLoggerDeviceData { unsigned int foundMessages; /* * The expected log message. The device will increase foundMessages if a * log message matches expectedMessage. */ const char *expectedMessage; /* * Match against a non-constant string that can be modified at run-time. * The log first has to match against expectedMessage. If that happens and * additionalMessage is not NULL, a match for additionalMessage is also * looked for. */ const char *additionalMessage; /* * The expected substrings in the log messages. The device will * increase foundMessages if a log message contains all of the * expectedSubStrings. * * If expectedSubStrings is set, expectedMessage and additionalMessage * are ignored. expectedSubStrings is preferred over expectedMessage and * additionalMessage. */ const char *expectedSubStrings[DDS_C_TEST_HELPER_LOGGER_DEVICE_DATA_MAX_SUBSTRINGS]; /* * Use this semaphore when multiple participants are concurrently producing * the expected log message. In that case, two participants may try to * increment foundMessages at the same time, and the final result could be * that foundMessages is only incremented once. So we need a mutex to * protect foundMessages. * * Use it as well when your test changes the expected message at runtime. * DDSCTesterHelperLoggerDeviceData_changeExpectedMessage takes care of it. */ struct RTIOsapiSemaphore *semaphore; /* * When a DomainParticipant is created in licensed builds, a log message * with the license information is printed. This boolean indicates * whether we want to ignore that message or not. * By default, it is set to RTI_TRUE; */ RTIBool ignoreLicenseRelatedMessages; }; #define DDSCTesterHelperLoggerDeviceData_INITIALIZER(expectedMessage__) { \ 0, /* foundMessages */ \ (expectedMessage__), \ NULL, /* additionalMessage */ \ {NULL}, /* expectedSubStrings */ \ NULL, /* semaphore */ \ RTI_TRUE /* ignoreLicenseRelatedMessages */ \ } #define DDSCTesterHelperLoggerDeviceDataPropertyValidation_INITIALIZER \ DDSCTesterHelperLoggerDeviceData_INITIALIZER("Unexpected property") extern DDSCTESTDllExport void DDSCTesterHelper_loggerDeviceWrite( struct NDDS_Config_LoggerDevice *device, const struct NDDS_Config_LogMessage *message); extern DDSCTESTDllExport void DDSCTesterHelperLoggerDeviceData_finalize( struct DDSCTesterHelperLoggerDeviceData *deviceData); extern DDSCTESTDllExport RTIBool DDSCTesterHelperLoggerDeviceData_initialize( struct DDSCTesterHelperLoggerDeviceData *deviceData); /* * Update the expected message safely when you may get multiple occurrences of * the previous expected message. Use it when the previous and the new expected * messages may be logged very closely together in time. * * This function takes the logger device data semaphore before changing the * expected message, and gives it afterwards. Doing so prevents against race * conditions in DDSCTesterHelper_loggerDeviceWrite between matching of the * expectedMessage and increments of the foundMessages: * - A match happens for the (old) expectedMessage. * - foundMessage becomes true. * - We change the expectedMessage and reset foundMessages to 0. * - foundMessages is increased because of the match with the old * expectedMessage. */ extern DDSCTESTDllExport RTIBool DDSCTesterHelperLoggerDeviceData_changeExpectedMessage( struct DDSCTesterHelperLoggerDeviceData *deviceData, const char *expectedMessage); /* * Caches the logging configuration so it can be restored later. * * This function is not thread safe: it should only be called in the tester main * thread. */ extern DDSCTESTDllExport RTIBool DDSCTesterHelper_cacheLoggingConfiguration(void); /* * Restores a cached logging configuration. * * This function is not thread safe: it should only be called in the tester main * thread, and only after a successful call to * DDSCTesterHelper_cacheLoggingConfiguration. */ extern DDSCTESTDllExport RTIBool DDSCTesterHelper_restoreLoggingConfiguration(void); /* * Gets the instanceHandle of a participant so that another participant can * refer to it when calling APIs. */ extern DDSCTESTDllExport RTIBool DDSCTesterHelper_getParticipantInstanceHandle( DDS_InstanceHandle_t *instanceHandle, DDS_DomainParticipant *participant); struct RTIDDSCTestOdbcDatabaseInfo { char DSN[DDS_C_TEST_DSN_MAX_LENGTH]; char odbcDatabaseLib[DDS_C_TEST_LIBNAME_MAX_LENGTH]; }; /* * If you modify this structure, make sure you properly update both dds_c and * security initializers (this includes all the different versions of * RTIDDSCTestSetting_init and the RTISecurityTestSetting_init function). */ struct RTIDDSCTestSetting { struct RTITestSetting parent; int numOdbcDatabases; int odbcDatabaseIndex; struct RTIDDSCTestOdbcDatabaseInfo testOdbcDatabaseInfo[DDS_C_TEST_MAX_TEST_DATABASES]; const char *libraryName; const char *profileName; }; /** * @ingroup DDSCTestHelpers * @brief Creates a participant in an scenario where no participants are * expected to detect interferences. * @param domainId /b In. The domain ID to be monitored. */ extern DDSCTESTDllExport RTIBool DDSCTestHelper_detectInterferingParticipants(int domainId); /* * @brief Sets the builtin_discovery_plugins in the default domain participant * profile and caches the current value. * * @param plugins In. Plugins to set default to. * @param cachedPlugins Out. Previous value of plugins in default profile. * * @return RTI_TRUE if success, RTI_FALSE if failure. */ extern DDSCTESTDllExport RTIBool DDSCTesterHelper_setAndCacheDefaultDomainParticipantQosDiscoveryPlugins( DDS_DiscoveryConfigBuiltinPluginKindMask plugins, DDS_DiscoveryConfigBuiltinPluginKindMask *cachedPlugins); /** * @brief Skips past the inline QoS of a DATA submessage. * @param stream /b In/Out. A stream that's currently positioned * at the start of the inline QoS (i.e., after * skipping octetsToInlineQos number of bytes). If * there is inline QoS, then the final position * will be after the inline QoS. * @param flags /b In. The flags of the submessage. If the flags * don't indicate that there is inline QoS, then * nothing is skipped. */ Public DDSCTESTDllExport RTIBool DDSCTesterHelper_skipInlineQos(struct RTICdrStream *stream, RTI_UINT8 flags); /** * @brief Checks if a local endpoint has already matched with a remote endpoint. * @pre localParticipant is not NULL. * @pre remoteEndpointGuid is not NULL. * @param localParticipant \b In. Participant which tables we'll go over to * check if the endpoints have matched. * @param localEndpointOid \b In. Object id of the local endpoint. * @param remoteEndpointGuid \b In. Pointer to the remote endpoint guid. * @param requiresCompatibility \b In. Indicates if the endpoints require to be * compatible for the match to be accepted. */ Public DDSCTESTDllExport RTIBool DDSCTesterHelper_isRemoteEndpointMatched( DDS_DomainParticipant *localParticipant, MIGRtpsObjectId localEndpointOid, struct MIGRtpsGuid *remoteEndpointGuid, RTIBool requiresCompatibility); /** * @brief Entry point for the dummy trust plugins that we can * use for testing. * @param security /b Out. The trust plugins to be created. * @param properties /b In. The properties that configure the * trust plugins. */ Public DDSCTESTDllExport void DDSCDomainParticipantTrustPluginsTester_securityCreate( struct DDS_TrustPluginSuite **security, const struct DDS_PropertyQosPolicy *properties); extern DDSCTESTDllExport RTIBool DDSCTestHelper_initializeFactoryQosForXMLWithExtraProfileFile( const struct RTITestSetting *setting, struct DDS_DomainParticipantFactoryQos *factoryQos, const char *extraProfileFile); extern DDSCTESTDllExport RTIBool DDSCTestHelper_initializeFactoryQosForXML( const struct RTITestSetting *setting, struct DDS_DomainParticipantFactoryQos *factoryQos); extern DDSCTESTDllExport RTIBool DDSCTestHelper_initializeMultiChannelQosPolicy( struct DDS_MultiChannelQosPolicy *policy, DDS_DomainId_t domainId, RTIBool keyed); extern DDSCTESTDllExport RTIBool DDSCTestHelper_configureFactoryWithSingleXmlFile( const struct RTITestSetting *setting, const char *profileFile); extern DDSCTESTDllExport void DDSCTestHelper_finalizeFactoryQosForXML(void); extern DDSCTESTDllExport RTIBool DDSCTestHelper_DomainParticipantFactoryQosEquals( const struct DDS_DomainParticipantFactoryQos *left, const struct DDS_DomainParticipantFactoryQos *right); extern DDSCTESTDllExport RTIBool DDSCTestHelper_DomainParticipantQosEquals( struct DDS_DomainParticipantQos *left, const struct DDS_DomainParticipantQos *right); extern DDSCTESTDllExport RTIBool DDSCTestHelper_DataWriterQosEquals( struct DDS_DataWriterQos *left, const struct DDS_DataWriterQos *right); extern DDSCTESTDllExport RTIBool DDSCTestHelper_PublisherQosEquals( const struct DDS_PublisherQos *left, const struct DDS_PublisherQos *right); extern DDSCTESTDllExport RTIBool DDSCTestHelper_DataReaderQosEquals( struct DDS_DataReaderQos *left, const struct DDS_DataReaderQos *right); extern DDSCTESTDllExport RTIBool DDSCTestHelper_SubscriberQosEquals( const struct DDS_SubscriberQos *left, const struct DDS_SubscriberQos *right); extern DDSCTESTDllExport DDS_ReturnCode_t DDSCTestHelper_waitForData( int numSamples, DDS_DataReader *reader, int timeoutSecs); extern DDSCTESTDllExport DDS_ReturnCode_t DDSCTestHelper_waitForDataAdv( int numSamples, DDS_DataReader *reader, int timeoutSecs, RTIBool timeoutIsExpected); /** * @brief Waits for numDisposed instances in the reader. * * @param numDisposed \b In. Number of instances to wait for. * @param reader \b In. Reader to wait for the instances. * @param timeoutSecs \b In. Amount of seconds to wait for the instances. * * @return DDS_RETCODE_OK if success, DDS_RETCODE_TIMEOUT otherwise. */ extern DDSCTESTDllExport DDS_ReturnCode_t DDSCTestHelper_waitForDispose( int numDisposed, DDS_DataReader *reader, int timeoutSecs); /** * @brief Waits for an ack from the reader and makes sure it hasn't nacked any * samples. * * @param writer \b In. * @param reader \b In. * @param timeoutSecs \b In. Amount of seconds to wait for the ack. * @return DDS_RETCODE_OK if an ack was received and no sample was nacked, * DDS_RETCODE_TIMEOUT if no ack was received, DDS_RETCODE_ERROR otherwise. */ extern DDSCTESTDllExport DDS_ReturnCode_t DDSCTestHelper_waitForAck( DDS_DataWriter *writer, DDS_DataReader *reader, int timeoutSecs); extern DDSCTESTDllExport struct DDS_TypeCode * DDSCTestHelper_getTypeCodeFromXMLFile( const char *typeName, const char *fileName, const char *filePath); extern DDSCTESTDllExport struct DDS_TypeObject * DDSCTestHelper_getTypeObjectFromXMLFile( const char *typeName, const char *fileName, const char *filePath); extern DDSCTESTDllExport struct DDS_TypeObjectV2 * DDSCTestHelper_getTypeObjectV2FromXMLFile( const char *typeName, const char *fileName, const char *filePath); extern DDSCTESTDllExport void DDSCTestHelperParticipantQos_disableTypePropagation( struct DDS_DomainParticipantQos *participantQos); extern DDSCTESTDllExport RTIBool DDSCTestHelperParticipantQos_typePropagationDisabled( const struct DDS_DomainParticipantQos *participantQos); extern DDSCTESTDllExport RTIBool DDSCTestHelperParticipantQos_setEndianness( struct DDS_DomainParticipantQos *participantQos, MIGGeneratorEndian endian); extern DDSCTESTDllExport void DDSCTestHelperEntity_printWithGuid( DDS_Entity *entity, const char *stringToPrint); /* * Get instance handles of fully discovered participants and the count. * * @param participant Local participant to get discovered participants of. * @param discPartSeqPtr Out. Populated with instance handles of discovered * remote participants. * * @return Number of fully discovered participants. */ extern DDSCTESTDllExport int DDSCDomainParticipantTester_getDiscoveredParticipants( DDS_DomainParticipant *participant, struct DDS_InstanceHandleSeq *discPartSeqPtr); /* * Get instance handles of partially discovered participants and the count. * * @param participant Local participant to get discovered participants of. * @param discPartSeqPtr Out. Populated with instance handles of discovered * remote participants. * * @return Number of partially discovered participants. */ extern DDSCTESTDllExport int DDSCDomainParticipantTester_getPartiallyDiscoveredParticipants( DDS_DomainParticipant *participant, struct DDS_InstanceHandleSeq *discPartSeqPtr); extern DDSCTESTDllExport RTIBool DDSCTestHelperUdpv4Property_setOnlyLoopbackAllowed( struct NDDS_Transport_UDPv4_Property_t *udpv4Property); extern DDSCTESTDllExport RTIBool DDSCTestHelperUdpv4Property_setNoInterfacesAllowed( struct NDDS_Transport_UDPv4_Property_t *udpv4Property); extern DDSCTESTDllExport void DDSCTestHelperUdpv4Property_finalizeInterfaceList( struct NDDS_Transport_UDPv4_Property_t *udpv4Property); extern DDSCTESTDllExport RTIBool DDSCTestHelper_setDefaultQosFromProfile( DDS_DomainParticipant *participant, DDS_Publisher *publisher, DDS_Subscriber *subscriber, const char *libraryName, const char *profileName); extern DDSCTESTDllExport RTITestReturnCode DDSCTestHelper_runTestWithQoSProfile( const struct RTITestSetting *setting, const char *libraryName, const char *profileName, RTITestFunction testFunction); extern DDSCTESTDllExport RTITestReturnCode DDSCTestHelper_runTestWithDiscoveryPlugins( const struct RTITestSetting *setting, const char *METHOD_NAME, RTITestFunction testToRun, DDS_DiscoveryConfigBuiltinPluginKindMask plugins); #define DDSCTestHelper_runTestWithSpdp2(setting__, METHOD_NAME__, testToRun__) \ DDSCTestHelper_runTestWithDiscoveryPlugins( \ (setting__), \ (METHOD_NAME__), \ (testToRun__), \ DDS_DISCOVERYCONFIG_BUILTIN_SDP2) extern DDSCTESTDllExport RTIBool DDSCTestHelper_fileExistsInResourceDir( const struct RTITestSetting *setting, const char *fileName); /** * @brief Checks if the remote DDS_DomainParticipant discovered is in an * external process and if so, ignores it completely to provide insulation * against test interference. This idea is based on the one adopted in * router.1.0 TestSystem.c. * * @param[in] reader * The builtin data reader associated with the DDS_PARTICIPANT_TOPIC_NAME topic * * @param[in] participantData * Individual data item received as a part of calling take() or read() * * @param[in] sampleInfo * The sample info for the data corresponding to participantData argument * * @param[out] participantIgnored * RTI_TRUE if an external remote participant was detected and ignored * successfully RTI_FALSE otherwise * * @return RTI_TRUE if the function processed the * DDS_ParticipantBuiltinTopicData successfully RTI_FALSE otherwise. */ extern DDSCTESTDllExport RTIBool DDSCTesterHelper_ignoreExternalRemoteDomainParticipant( DDS_DataReader *reader, struct DDS_ParticipantBuiltinTopicData *participantData, struct DDS_SampleInfo *sampleInfo, RTIBool *participantIgnored); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_initialize_enum_member( struct DDS_EnumMemberSeq *members, DDS_Long index, const char *name, DDS_Long ordinal); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_finalize_enum_member( struct DDS_EnumMemberSeq *members, DDS_Long index); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_initialize_union_member( struct DDS_UnionMemberSeq *members, DDS_Long index, const char *name, struct DDS_LongSeq *labels, DDS_TypeCode *tc); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_finalize_union_member( struct DDS_UnionMemberSeq *members, DDS_Long index); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_initialize_value_member( struct DDS_ValueMemberSeq *members, DDS_Long index, const char *name, DDS_Boolean isKey, DDS_Boolean isOptional, DDS_TypeCode *tc, DDS_Visibility access); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_finalize_value_member( struct DDS_ValueMemberSeq *members, DDS_Long index); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_initialize_st_member( struct DDS_StructMemberSeq *stMembers, DDS_Long index, const char *name, DDS_Boolean isKey, DDS_Long id, DDS_Boolean isOptional, DDS_TypeCode *tc); extern DDSCTESTDllExport RTIBool DDSCTesterTypeCodeHelper_finalize_st_member( struct DDS_StructMemberSeq *stMembers, DDS_Long index); /** * @brief Blocks the send operation on a transport * * After calling this operation a Participant will not send data using * transport with name transportName. * This can be used to force liveliness loss. * * @param participant Participant to block send on * @param oldSendFunction Out. Old send function is stored in this field if * it is not NULL. * @param transportName Transport to block send on. * * @return RTI_TRUE if success, RTI_FALSE if failure. */ extern DDSCTESTDllExport RTIBool DDSCTestHelper_blockTransportSend( DDS_DomainParticipant *participant, NDDS_Transport_Send_Fcn *oldSendFunction, const char *transportName); /** * @brief Unblocks the send operation on a transport. * * oldSendFunction must be the output value obtained after calling * DDSCTestHelper_blockTransportSend */ extern DDSCTESTDllExport RTIBool DDSCTestHelper_unblockTransportSend( DDS_DomainParticipant *participant, NDDS_Transport_Send_Fcn oldSendFunction, const char *transportName); /** * @brief Block participant from receiving any messages from participantToBlock. * * @param participant Participant that should stop receiving messages. * @param participantToBlock Participant that we should block messages from. * @param transportName Transport to block messages on (must be a udpv plugin). * * @return RTI_TRUE if success, RTI_FALSE if error */ RTIBool DDSCTestHelper_blockReceiveFromParticipant( DDS_DomainParticipant *participant, DDS_DomainParticipant *participantToBlock, DDS_TransportBuiltinKind transportKind); /** * @brief Allow participant to again receive messages from any blocked * participants. * * @param participant Participant that should begin receiving messages again. * @param transportName Transport to block messages on (must be a udpv plugin). * * @return RTI_TRUE if success, RTI_FALSE if error */ RTIBool DDSCTestHelper_unblockReceiveFromParticipant( DDS_DomainParticipant *participant, DDS_TransportBuiltinKind transportKind); /* * @brief Get the value of some internal state in the reader queue. * * @param reader the reader to get the queue from * @param topicQueryGuid if you would like access to a specific topic query * queue instead of the live data queue pass in a non-nil guid for the * topic query. passing in DDS_GUID_UNKNOWN for the topicQueryGuid param * will return the live data reader queue * @param status the status to populate with various counters from the queue * * @return DDS_BOOLEAN_TRUE on success. DDS_BOOLEAN_FALSE on failure, most * likely because the queue is not found */ extern DDSCTESTDllExport DDS_Boolean DDSCTestHelper_getDataReaderQueueStatus( DDS_DataReader *reader, const struct DDS_GUID_t *topicQueryGuid, PRESReaderQueueStatus *status); /** * @brief Report whether a specific remote writer queue exists in the data * reader. * * @param reader \b In. The data reader to find the queue from. * @param topicQueryGuid \b In. If you would like to find a specific topic query * queue instead of the live data queue pass in a non-nil guid for the * topic query. Passing in DDS_GUID_UNKNOWN for the topicQueryGuid * param will return the live data reader queue. * @param writerGuid \b In. The guid of the remote writer whose queue is to be * found. * * @returns DDS_BOOLEAN_TRUE if the queue is found, DDS_BOOLEAN_FALSE otherwise. */ DDS_Boolean DDSCTestHelper_dataReaderRemoteWriterQueueExists( DDS_DataReader *reader, const struct DDS_GUID_t *topicQueryGuid, const struct DDS_GUID_t *writerGuid); /* * @brief Get the value of some internal state in the remote writer queue. * * @param reader the reader to get the queue from * @param topicQueryGuid if you would like access to a specific topic query * queue instead of the live data queue pass in a non-nil guid for the * topic query. passing in DDS_GUID_UNKNOWN for the topicQueryGuid param * will return the live data reader queue * @param writerGuid the guid of the remote writer to look the count up for * @param status the status to populate with various counters from the queue * * @return DDS_BOOLEAN_TRUE on success. DDS_BOOLEAN_FALSE on failure, most * likely because the queue is not found */ extern DDSCTESTDllExport DDS_Boolean DDSCTestHelper_getDataReaderRemoteWriterQueueStatus( DDS_DataReader *reader, const struct DDS_GUID_t *topicQueryGuid, const struct DDS_GUID_t *writerGuid, PRESReaderQueueRemoteWriterQueueStatus *status); extern DDSCTESTDllExport RTIBool DDSCTestHelper_checkDataReaderInstanceStatistics( const struct DDS_DataReaderCacheStatus *expected, const struct DDS_DataReaderCacheStatus *actual); extern DDSCTESTDllExport RTIBool DDSCTestHelper_checkDataWriterInstanceStatistics( const struct DDS_DataWriterCacheStatus *expected, const struct DDS_DataWriterCacheStatus *actual); extern DDSCTESTDllExport int DDSCTestHelper_getUDPv4interfacesCount( DDS_DomainParticipant *self, NDDS_Transport_ClassId_t transport); extern DDSCTESTDllExport RTIBool DDSCTestHelper_setSubmessageLength( struct RTICdrStream *stream, /* out */ struct REDABuffer *buffers, /* in */ RTI_UINT16 newLength); extern DDSCTESTDllExport RTIBool DDSCTestHelper_positionStreamToBinaryProperty( struct RTICdrStream *stream, char *buffer, RTI_INT32 bufferLength, const char *propertyName); extern DDSCTESTDllExport RTIBool DDSCTestHelper_positionStreamToNextPid(struct RTICdrStream *stream); extern DDSCTESTDllExport RTIBool DDSCTestHelper_positionStreamToPid( struct RTICdrStream *stream, struct REDABuffer *buffer, MIGRtpsParameterId pidToFind, RTIBool skipEncapsulation); /** * @brief Skips submessages until it reaches a specific submessage. * * @param bufferOut \b Out. Output buffer object that will be set with the * position and length of the found submessage. Cannot be NULL. * @param bytesSkipped \b Out. Number of bytes skipped until it reached the * submessage. * @param bufferIn \b In. Input buffer containing a set of submessages to search * in. Cannot be NULL. * @param requestedSubmessageId \b In. ID of the submessage to be found. * @return DDS_RETCODE_OK if the submessage was found and the output buffer is * set correctly, DDS_RETCODE_ERROR otherwise. */ extern DDSCTESTDllExport DDS_ReturnCode_t DDSCTestHelper_positionBufferToSubmessageId( struct REDABuffer *bufferOut, int *bytesSkipped, const struct REDABuffer *bufferIn, MIGRtpsSubmessageId requestedSubmessageId); extern DDSCTESTDllExport void DDSCTestHelper_onAfterRemoteParticipantAuthenticatedCheckLiveliness( struct DISCParticipantDiscoveryListener *listener, struct DISCParticipantDiscoveryPlugin *plugin, const struct DISCBuiltinTopicParticipantData *data, const struct DISCPluginCustomOptions *pluginOptions, const struct DISCPluginListenerStorage *listenerStorage, struct REDAWorker *worker); struct DDSCTestHelper_onDataAvailableListenerStorage { int nonSecureAliveSamplesReceived; int secureAliveSamplesReceived; int nonSecureDisposeSamplesReceived; int secureDisposeSamplesReceived; struct PRESParticipantChannelReaderListener originalListener; }; #define DDSCTestHelper_onDataAvailableListenerStorage_INITIALIZER \ { \ 0, /* nonSecureAliveSamplesReceived */ \ 0, /* secureAliveSamplesReceived */ \ 0, /* nonSecureDisposeSamplesReceived */ \ 0, /* secureDisposeSamplesReceived */ \ PRESParticipantChannelReaderListener_INITIALIZER /* originalListener */ \ } extern DDSCTESTDllExport RTIBool DDSCTestHelper_setTestOnAfterRemoteParticipantAuthenticated( DDS_DomainParticipant *participant, RTIBool *result, RTIBool shutdownLivelinessOnAuth, DISCParticipantDiscoveryListenerOnAfterRemoteParticipantAuthenticatedCallback onAfterRemoteParticipantAuthenticated); extern DDSCTESTDllExport RTIBool DDSCDomainParticipantQos_setTestSPDP2LivelinessQosPolicies( struct DDS_DomainParticipantQos *participantQos, int initialParticipantAnnouncements, const struct DDS_Duration_t *minInitialParticipantAnnouncementPeriod, const struct DDS_Duration_t *maxInitialParticipantAnnouncementPeriod, const struct DDS_Duration_t *participantLivelinessAssertPeriod, const struct DDS_Duration_t *participantAnnouncementPeriod, const struct DDS_Duration_t *participantLivelinessLeaseDuration, const struct DDS_Duration_t *maxLivelinessLossDetectionPeriod, const struct DDS_Duration_t *secureVolatileWriterFastHeartBeatPeriod); struct DDSCTestHelperDirectedWriteListenerData { RTIBool success; PRESDirectedWriteSerializationKind serializationKind; RTIBool isRti; RTIBool isRtps24; RTIBool delayPublicationDiscovery; struct PRESProductVersion *productVersion; struct MIGRtpsGuid *guid; }; #define DDSCTestHelperDirectedWriteListenerData_INITIALIZER \ { \ RTI_FALSE, /* success */ \ PRES_DIRECTED_WRITE_AUTO_SERIALIZATION, /* serializationKind */ \ RTI_FALSE, /* isRti */ \ RTI_FALSE, /* isRtps24 */ \ RTI_FALSE, /* delayPublicationDiscovery */ \ NULL, /* productVersion */ \ NULL /* guid */ \ } extern DDSCTESTDllExport void DDSCTestHelper_onBeforeFlushChangeVendorIdAndProtocolVersion( void *ldata, struct REDABuffer *buffers, int bufferCount, const struct MIGRtpsGuid *senderParticipantId); extern DDSCTESTDllExport void DDSCTestHelper_onBeforeEndSubmessageChangeVendorId( void *ldata, struct REDABuffer *buffers, int bufferCount, MIGRtpsSubmessageId submessageId, const struct MIGRtpsGuid *senderGuid); extern DDSCTESTDllExport void DDSCTestHelper_setupNonRtiTamperingListener( struct MIGGeneratorListener *listener, struct DDSCTestHelperDirectedWriteListenerData *listenerData, RTIBool isUsingSecurity); struct DDSCTestHelperVendorBuiltinEndpointsListenerData { DDS_UnsignedLong expectedVendorBuiltinEndpoints; RTIBool result; }; #define DDSCTestHelperVendorBuiltinEndpointsListenerData_INITIALIZER \ { \ 0, /* expectedVendorBuiltinEndpoints */ \ RTI_FALSE /* result */ \ } extern DDSCTESTDllExport void DDSCTestHelper_checkVendorBuiltinEndpointsOnBeforeEndSubmessage( void *ldata, struct REDABuffer *buffers, int bufferCount, MIGRtpsSubmessageId submessageId, const struct MIGRtpsGuid *senderGuid); extern DDSCTESTDllExport RTIBool DDSCTestHelper_setAndCacheAutoEnableCreatedEntities( DDS_Boolean *cachedValue, DDS_Boolean setValue); extern DDSCTESTDllExport RTIBool DDSCTestHelper_setBuiltinReaderListener( DDS_DomainParticipant *participant, const char *builtinTopicName, const struct DDS_DataReaderListener *listener, DDS_StatusMask listenerStatusMask); typedef struct DDSCTestHelperLocatorCheckerListenerData { struct DDS_Locator_t expectedLocator; /* * Set to RTI_TRUE by the participant builtin listener to indicate that * it discovered a participant with a locator equals to expectedLocator. */ RTIBool locatorFound; RTI_INT32 maxLocatorExpected; RTIBool error; } DDSCTestHelperLocatorCheckerListenerData; /* * The constant static variable DDS_LOCATOR_INVALID can not be used to * initialize a structure as some compilers. */ #define DDSC_TEST_HELPER_DDS_LOCATOR_INVALID { \ -1, /* kind */ \ 0, /* port */ \ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* address */ \ DDS_SEQUENCE_INITIALIZER /* encapsulations */ \ } #define DDSCTestHelperLocatorCheckerListenerData_INITIALIZER { \ DDSC_TEST_HELPER_DDS_LOCATOR_INVALID, /* expectedLocator */ \ RTI_FALSE, /* locatorFound */ \ RTI_INT32_MAX, /* maxLocatorExpected */ \ RTI_FALSE /* error */ \ } extern DDSCTESTDllExport void DDSCTestHelper_onDataAvailableParticipantLocatorChecker( void *listener_data, DDS_DataReader *reader); extern DDSCTESTDllExport void DDSCTestHelper_onDataAvailableSubscriptionLocatorChecker( void *listener_data, DDS_DataReader *reader); extern DDSCTESTDllExport void DDSCTestHelper_onDataAvailablePublicationLocatorChecker( void *listener_data, DDS_DataReader *reader); extern DDSCTESTDllExport struct RTIClock *DDSCTestHelper_installMockClock( const struct RTIMockClockProperty *mockClockProperty); extern DDSCTESTDllExport DDS_Boolean DDSCTestHelper_uninstallMockClock( struct RTIClock *clock); extern DDSCTESTDllExport RTIBool DDSCTestHelper_setTestParticipantDiscOnDataAvailable( DDS_DomainParticipant *participant, MIGRtpsObjectId readerObjectId, MIGRtpsObjectId secureReaderObjectId, struct DDSCTestHelper_onDataAvailableListenerStorage *listenerStorage, PRESPsReaderListenerOnDataAvailableCallback onDataAvailable); extern DDSCTESTDllExport RTIBool DDSCTestHelper_getRemoteParticipantData( DDS_DomainParticipant *participant, struct DDS_ParticipantBuiltinTopicData *participantData, DDS_DomainParticipant *remoteParticipant); extern DDSCTESTDllExport MIGRtpsObjectId DDSCTestHelper_getWriterObjectIdInFlush( struct REDABuffer *buffers, const int bufferCount); /* * FUZZ TESTING RELATED */ typedef enum { DDS_C_TEST_HELPER_NO_LOG_EXPECTED = 0, DDS_C_TEST_HELPER_EXPECTED_WARNING = 1, DDS_C_TEST_HELPER_EXPECTED_ERROR = 2 } DDSCTestHelperExpectedLogging; /* * @brief Reads a binary file named fileName, which should be located in * dds_c.1.0/resource/fuzzerTestFiles, and store the content in data. * @pre The tester must be able to open file. We can use * RTITestSetting_fileTestIsSupport to verify this. * @param setting \b In. Test settings. * @param data \b Out. Array where the file content will be stored. Should be * NULL and should be freed after use it. * @param size \b Out. Size of the file content. Cannot be NULL. * @param fileName \b In. File name of the packet. It should be located in * dds_c.1.0/resource/fuzzerTestFiles. * @return DDS_RETCODE_OK if success, DDS_RETCODE_UNSUPPORTED if we don't have * available a file system, DDS_RETCODE_ERROR otherwise. */ extern DDSCTESTDllExport DDS_ReturnCode_t DDSCTestHelper_readFuzzInputFile( const struct RTITestSetting *setting, unsigned char **data, size_t *size, const char *fileName); /** * @brief Copy the content of src onto dest and terminate it with the null * terminator. If the provided dest is NULL memory will be allocated for it. * * @param[out] dest Pointer to the destination array where the content is to * be copied. * @param[in] src Data to be copied. * @param[in] size Size of the data to be copied. * * @pre if provided, the size of dest must be at least size bytes if src is NULL * terminated or size+1 bytes if src is not NULL terminated. * @pre src must contain at least size bytes. * * @return DDS_ReturnCode_t Result of the operation. */ extern DDSCTESTDllExport DDS_ReturnCode_t DDSCTestHelper_copyStringAndNullTerminate( char **dest, const RTI_UINT8 *src, size_t size); /* * END OF FUZZ TESTING RELATED */ /* * Enum used by * DDSCDomainParticipantDiscoverySpdp2Tester_testSpdp2NoConfigNewParticipantWithParams * and * DDSCBuiltinUdpv4WanTester_testSpdp2NoConfigNewParticipantWithParams * to determine when to call add_peer() with an existing locator. */ typedef enum { /* Do not call add_peer(), existing locator should be on initial_peers */ DDSC_SPDP2_TESTER_NO_ADD_PEER, /* * Call add_peer() before rediscovering a new participant with the same * locators */ DDSC_SPDP2_TESTER_ADD_PEER_BEFORE_REDISCOVERY, /* * Call add_peer() after rediscovering a new participant with the same * locators */ DDSC_SPDP2_TESTER_ADD_PEER_AFTER_REDISCOVERY } DDSCDomainParticipantDiscoverySpdp2TesterAddPeerTestCase; /* * Used with * DDSCTestHelper_onBeforeEndSubmessageTamperData * and * RTI_Security_DomainParticipantSpdp2Tester_onBeforeEndSubmessageTamperConfigChannel * to test a lost sample on the config channel or on the secure volatile * channel. */ Package struct DDSCTestHelperTamperingListenerData { /* Set to true if there is a failure when tampering the data */ RTIBool error; /* * If this is true we will corrupt the data section of messages from * writerToCorrupt */ RTIBool corruptData; /* * If this is true we will corrupt the INFO_DST of messages from * writerToCorrupt with the matching destGuidToCorrupt. */ RTIBool corruptInfoDst; /* * If this is true and corruptData is true we will corrupt either * the related writer guid or the related reader guid of messages sent * by writerToCorrupt. */ RTIBool corruptRelatedEntityGuid; /* Object ID of the writer to corrupt outgoing messages on */ MIGRtpsObjectId writerToCorrupt; /* * This field is used to either corrupt messages with an INFO_DST going * to this GUID (in nonsecure tests, through * DDSCTestHelper_onBeforeFlushTamperInfoDst) OR to corrupt secure volatile * messages related to this endpoint (in secure tests, through * DDSCTestHelper_onBeforeEndSubmessageTamperData). * * To corrupt the INFO_DST, corruptInfoDst must also be true. To corrupt * the secure volatile messages, corruptData must also be true. */ struct MIGRtpsGuid destGuidToCorrupt; /* * Set to TRUE when the first message is corrupted, use this to ensure * you don't move on before a corrupted message is sent */ RTIBool messageCorrupted; }; #define DDSCTestHelperTamperingListenerData_INITIALIZER \ { \ RTI_FALSE, /* error */ \ RTI_FALSE, /* corruptData */ \ RTI_FALSE, /* corruptInfoDst */ \ RTI_FALSE, /* corruptRelatedEntityGuid */ \ MIG_RTPS_OBJECT_ID_UNKNOWN, /* writerToCorrupt */ \ MIG_RTPS_GUID_UNKNOWN, /* destGuidToCorrupt */ \ RTI_FALSE /* messageCorrupted */ \ } /* * Tampers the submessage ID of a DATA submessage to cause it to be dropped * if listenerData->writerToCorrupt matches the writer OID of the sender or its * secure counterpart. * * @param lData Listener data * @param buffers Pointer to buffers * @param bufferCount Number of buffers * @param submessageId Submessage ID of the message being tampered * @param senderGuid GUID of the writer sending the message */ void DDSCTestHelper_onBeforeEndSubmessageTamperData( void *lData, struct REDABuffer *buffers, int bufferCount, MIGRtpsSubmessageId submessageId, const struct MIGRtpsGuid *senderGuid); /* * If the first submessage is an INFO_DST attached to a large message (> 128 * bytes) tamper the message. If listenerData->destGuidToCorrupt is set, * only tamper the message if the destination GUID matches. Otherwise tamper * all large INFO_DST messages. * * @param lData Listener data * @param buffers Pointer to buffers * @param bufferCount Number of buffers * @param submessageId Submessage ID of the message being tampered * @param senderGuid GUID of the writer sending the message */ void DDSCTestHelper_onBeforeFlushTamperInfoDst( /* inouts */ void *listenerData, struct REDABuffer *buffers, /* inputs */ int bufferCount, const struct MIGRtpsGuid *senderParticipantId); extern DDSCTESTDllExport RTIBool DDSCTestHelper_addPartition( struct DDS_PartitionQosPolicy *partitionQos, const char *partitionName); /** * @internal * * @brief Helper method for asserting the * COMMEND_READER_LOSS_PERCENTAGE_EXTENDED property. This property * configures the loss percentage of samples for a reader. * * @see COMMEND_READER_LOSS_PERCENTAGE and * COMMEND_STATELESS_READER_LOSS_PERCENTAGE. If several of those properties are * set, only one of them is applied following the order of precedence: * COMMEND_READER_LOSS_PERCENTAGE_EXTENDED > COMMEND_READER_LOSS_PERCENTAGE > * COMMEND_STATELESS_READER_LOSS_PERCENTAGE * * @param[in,out] policy The DDS_PropertyQosPolicy in which the property will * be asserted. * @param[in] dropPolicy The drop policy to be applied: * - Random - random samples or fragments will be dropped and accrued towards * the overall percentage of samples lost. * - Deterministic - loss is based on the sample sequence number or first * fragment number, (num % 100 / percentage, where 'num' is the sn or * fragment number) will be dropped. The formula is not perfect, it is an * approximation. For percentages greater than 50, all samples or fragments * will be dropped. * - NOTE: A DATA_FRAG submessage can contain more than one fragment. In that * case, to decide whether the DATA_FRAG is dropped, the first fragment * number is used. Therefore, if there are more than one fragment per * DATA_FRAG, there could be fragments in the lost interval that won't be * dropped, or fragments outside the lost interval that will be dropped. * @param[in] percentageLoss The percentage of samples or fragments that will be * dropped when using the random policy. When using the deterministic policy, * loss is determined as num % 100 / percentageLoss, where 'num' is the sn or * fragment number. * Range [0, 100]. * @param[in] firstLostSN The first sample sequence number that will be dropped. * Before this sequence number the sample will not be dropped. * Range [-1, 65535]. When set to -1, it is ignored. * @param[in] lastLostSN The last sample sequence number that will be dropped. * After this sequence number the sample will not be dropped. * Range [-1, 65535]. When set to -1, it is ignored. * @param[in] firstLostFrag The first fragment number that will be dropped. * Before this fragment number the fragment will not be dropped. * Range [-1, 255]. When set to -1, it is ignored. * @param[in] lastLostFrag The last fragment number that was dropped. After this * fragment number the fragment will not be dropped. * Range [-1, 255]. When set to -1, it is ignored. * @param[in] lossDuration The time in seconds that the samples will be lost. * Range [-1, 255]. When set to -1, it is ignored. * * @return RTI_TRUE if the property was successfully asserted, RTI_FALSE * otherwise. * * @example The order is as the parameters are described: * - "DETERMINISTIC_SAMPLE,100,-1,-1,-1,-1,-1" drop all the samples. * - "RANDOM_SAMPLE,20,-1,-1,-1,-1,5" drop random samples (overall 20%) * but not after 5 seconds. * - "DETERMINISTIC_SAMPLE,50,1,100,-1,-1,-1" drop every other sample from sequence number 1 to 100. * - "DETERMINISTIC_FRAGMENT,50,-1,-1,20,30,-1" drop every other fragment between first fragment numbers 20 to 30 for all samples. * - "RANDOM_FRAGMENT,20,5,10,1,5,-1" drop random samples and fragments * (overall 20%) between SN 5 and 10 and fragments between 1 and 5. */ extern DDSCTESTDllExport RTIBool DDSCTestHelper_assertDataReaderLossPercentagePropertyExt( DDS_PropertyQosPolicy *policy, COMMENDReaderLossKind dropPolicy, int percentageLoss, int firstLostSN, int lastLostSN, int firstLostFrag, int lastLostFrag, int lossDuration); /** * @internal * * @brief Returns a domain participant factory instance with monitoring * disabled. * * After MONITOR-709, the monitoring library is enabled by default. This caused * several existing tests (which assumed that the library was disabled) to start * failing. This helper allows those tests to continue running without * modification by providing a domain participant factory with monitoring * disabled. * * To restore the default configuration with monitoring enabled, call * DDSCTestHelper_restoreMonitoringDefaults or alternatively, finalize the * factory instance. * * @see DDSCTestHelper_restoreMonitoringDefaults. * * @return A pointer to a DDS_DomainParticipantFactory with monitoring disabled. */ extern DDSCTESTDllExport DDS_DomainParticipantFactory * DDSCTestHelper_disableMonitoringAndGetFactory(void); /** * @internal * * @brief Restores the default MonitoringQosPolicy values into the * DomainParticipantFactory QoS. * * @see DDSCTestHelper_disableMonitoringAndGetFactory. * * @return DDS_BOOLEAN_TRUE if the default configuration was successfully * restored, DDS_BOOLEAN_FALSE otherwise. */ extern DDSCTESTDllExport DDS_Boolean DDSCTestHelper_restoreMonitoringDefaults(void); /** * @brief Configure the participant Qos to use Type Object V2 or Type Object V1 * * @param participantQos The participant Qos to configure * @param useTypeObjectV2 RTI_TRUE to configure the participant to use Type * Object V2, RTI_FALSE to use Type Object V1 */ void DDSCTestHelper_configureParticipantQosTypeObject( struct DDS_DomainParticipantQos *participantQos, RTIBool useTypeObjectV2); #ifdef __cplusplus } #endif #endif /* ddsctesthelpers_testHelper_h */