diff --git a/CMakeLists.txt b/CMakeLists.txt index ee12730f..a094a550 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -307,4 +307,5 @@ if(NATS_BUILD_STREAMING) endif() add_subdirectory(test) add_subdirectory(test/dylib) +add_subdirectory(test/check_cpp) #---------------------------- diff --git a/buildOnTravis.sh b/buildOnTravis.sh index 8bc7da67..0510cf93 100755 --- a/buildOnTravis.sh +++ b/buildOnTravis.sh @@ -73,6 +73,14 @@ if [ $res -ne 0 ]; then exit $res fi +echo "Test C++ compiler compatibility" +# There is mo need to run check, just make sure it's compiled +bin/check_cpp +res=$? +if [ $res -ne 0 ]; then + exit $res +fi + export NATS_TEST_TRAVIS=yes echo "Using NATS server version: $NATS_TEST_SERVER_VERSION" ctest -L 'test' --timeout 60 --output-on-failure $4 diff --git a/src/nats.h b/src/nats.h index e368d89a..0e69b43a 100644 --- a/src/nats.h +++ b/src/nats.h @@ -1239,6 +1239,127 @@ typedef void (*jsFetchCompleteHandler)(natsConnection *nc, natsSubscription *sub */ typedef bool (*jsFetchNextHandler)(int *messages, int64_t *maxBytes, natsSubscription *sub, void *closure); +/** + * Async pull subscriber options. + * + * Part of #jsOptions. + */ +typedef struct jsOptionsPullSubscribeAsync +{ + int64_t Timeout; ///< Auto-unsubsribe after this many milliseconds. + int MaxMessages; ///< Auto-unsubscribed after receiving this many messages. + int64_t MaxBytes; ///< Auto-unsubscribe after receiving this many bytes. + + /// \brief If NoWait is set, the subscription will receive the + /// messages already stored on the server subject to the limits, + /// but will not wait for more messages. + /// + /// \note that if Timeout is set we would still wait for first + /// message to become available, even if there are currently any + /// on the server + bool NoWait; + + /// \brief Fetch complete handler that receives the exit status + /// code, the subscription's Complete handler is also invoked, + /// but does not have the status code. + jsFetchCompleteHandler CompleteHandler; + void *CompleteHandlerClosure; + + /// \brief Have server sends heartbeats at this interval (in + /// milliseconds) to help detect communication failures. + int64_t Heartbeat; + + /// @brief When using the automatic Fetch flow control (default + /// NextHandler), this is the number of messages to ask for in a + /// single request. + int FetchSize; + + /// @brief When using the automatic Fetch flow control (default + /// NextHandler), initiate the next fetch request (this many + /// messages) prior to the fulfillment of the current request. + /// + /// @note KeepAhead can not be used in conjunction with MaxBytes + /// or NoWait. + int KeepAhead; + + /// @brief If set, switches to manual fetch flow control. + /// + /// If provided, this function gets called before each message + /// is deliverered to msgCB, and overrides the default algorithm + /// for sending Next fetch requests. + jsFetchNextHandler NextHandler; + void *NextHandlerClosure; + +} jsOptionsPullSubscribeAsync; + +/** + * Async pull options. + * + * Part of #jsOptions. + */ +typedef struct jsOptionsPublishAsync +{ + int64_t MaxPending; ///< Maximum outstanding asynchronous publishes that can be inflight at one time. + + // If jsPubAckHandler is specified, the callback will be invoked + // for every asynchronous published message, either as a positive + // result, or with the error encountered when publishing that + // message. If this callback is specified, ErrHandler (see below) + // will be ignored. + jsPubAckHandler AckHandler; ///< Callback invoked for each asynchronous published message. + void *AckHandlerClosure; ///< Closure (or user data) passed to #jsPubAckHandler callback. + + // This callback is invoked for messages published asynchronously + // when an error is returned by the server or if the library has + // timed-out waiting for an acknowledgment back from the server + // (if publish uses the jsPubOptions.MaxWait). + jsPubAckErrHandler ErrHandler; ///< Callback invoked when error encountered publishing a given message. + void *ErrHandlerClosure; ///< Closure (or user data) passed to #jsPubAckErrHandler callback. + + int64_t StallWait; ///< Amount of time (in milliseconds) to wait in a PublishAsync call when there is MaxPending inflight messages, default is 200 ms. + +} jsOptionsPublishAsync; + +/** + * Advanced stream purge options + * + * * `Subject` will filter the purge request to only messages that match the subject, which can have wildcards.
+ * * `Sequence` will purge up to but not including this sequence and can be combined with subject filtering.
+ * * `Keep` will specify how many messages to keep and can be combined with subject filtering.
+ * + * \note `Sequence` and `Keep` are mutually exclusive, so both can not be set at the same time. + */ +typedef struct jsOptionsStreamPurge +{ + const char *Subject; ///< This is the subject to match against messages for the purge command. + uint64_t Sequence; ///< Purge up to but not including sequence. + uint64_t Keep; ///< Number of messages to keep. + +} jsOptionsStreamPurge; + +/** + * Advance stream information retrieval options + */ +typedef struct jsOptionsStreamInfo +{ + bool DeletedDetails; ///< Get the list of deleted message sequences. + const char *SubjectsFilter; ///< Get the list of subjects in this stream. + +} jsOptionsStreamInfo; + +/** + * Advanced stream options + * + * * `Purge` for advanced purge options. + * * `Info` for advanced information retrieval options. + */ +typedef struct jsOptionsStream +{ + jsOptionsStreamPurge Purge; ///< Optional stream purge options. + jsOptionsStreamInfo Info; ///< Optional stream information retrieval options. + +} jsOptionsStream; + /** * JetStream context options. * @@ -1246,118 +1367,12 @@ typedef bool (*jsFetchNextHandler)(int *messages, int64_t *maxBytes, natsSubscri */ typedef struct jsOptions { - const char *Prefix; ///< JetStream prefix, default is "$JS.API" - const char *Domain; ///< Domain changes the domain part of JetSteam API prefix. - int64_t Wait; ///< Amount of time (in milliseconds) to wait for various JetStream API requests, default is 5000 ms (5 seconds). - - struct jsOptionsPublishAsync - { - int64_t MaxPending; ///< Maximum outstanding asynchronous publishes that can be inflight at one time. - - // If jsPubAckHandler is specified, the callback will be invoked - // for every asynchronous published message, either as a positive - // result, or with the error encountered when publishing that - // message. If this callback is specified, ErrHandler (see below) - // will be ignored. - jsPubAckHandler AckHandler; ///< Callback invoked for each asynchronous published message. - void *AckHandlerClosure; ///< Closure (or user data) passed to #jsPubAckHandler callback. - - // This callback is invoked for messages published asynchronously - // when an error is returned by the server or if the library has - // timed-out waiting for an acknowledgment back from the server - // (if publish uses the jsPubOptions.MaxWait). - jsPubAckErrHandler ErrHandler; ///< Callback invoked when error encountered publishing a given message. - void *ErrHandlerClosure; ///< Closure (or user data) passed to #jsPubAckErrHandler callback. - - int64_t StallWait; ///< Amount of time (in milliseconds) to wait in a PublishAsync call when there is MaxPending inflight messages, default is 200 ms. - - } PublishAsync; ///< extra options for #js_PublishAsync - - struct jsOptionsPullSubscribeAsync - { - int64_t Timeout; ///< Auto-unsubsribe after this many milliseconds. - int MaxMessages; ///< Auto-unsubscribed after receiving this many messages. - int64_t MaxBytes; ///< Auto-unsubscribe after receiving this many bytes. - - /// \brief If NoWait is set, the subscription will receive the - /// messages already stored on the server subject to the limits, - /// but will not wait for more messages. - /// - /// \note that if Timeout is set we would still wait for first - /// message to become available, even if there are currently any - /// on the server - bool NoWait; - - /// \brief Fetch complete handler that receives the exit status - /// code, the subscription's Complete handler is also invoked, - /// but does not have the status code. - jsFetchCompleteHandler CompleteHandler; - void *CompleteHandlerClosure; - - /// \brief Have server sends heartbeats at this interval (in - /// milliseconds) to help detect communication failures. - int64_t Heartbeat; - - /// @brief When using the automatic Fetch flow control (default - /// NextHandler), this is the number of messages to ask for in a - /// single request. - int FetchSize; - - /// @brief When using the automatic Fetch flow control (default - /// NextHandler), initiate the next fetch request (this many - /// messages) prior to the fulfillment of the current request. - /// - /// @note KeepAhead can not be used in conjunction with MaxBytes - /// or NoWait. - int KeepAhead; - - /// @brief If set, switches to manual fetch flow control. - /// - /// If provided, this function gets called before each message - /// is deliverered to msgCB, and overrides the default algorithm - /// for sending Next fetch requests. - jsFetchNextHandler NextHandler; - void *NextHandlerClosure; - - } PullSubscribeAsync; ///< extra options for #js_PullSubscribeAsync - - - /** - * Advanced stream options - * - * * `Purge` for advanced purge options. - * * `Info` for advanced information retrieval options. - */ - struct jsOptionsStream - { - /** - * Advanced stream purge options - * - * * `Subject` will filter the purge request to only messages that match the subject, which can have wildcards.
- * * `Sequence` will purge up to but not including this sequence and can be combined with subject filtering.
- * * `Keep` will specify how many messages to keep and can be combined with subject filtering.
- * - * \note `Sequence` and `Keep` are mutually exclusive, so both can not be set at the same time. - */ - struct jsOptionsStreamPurge - { - const char *Subject; ///< This is the subject to match against messages for the purge command. - uint64_t Sequence; ///< Purge up to but not including sequence. - uint64_t Keep; ///< Number of messages to keep. - - } Purge; ///< Optional stream purge options. - - /** - * Advance stream information retrieval options - */ - struct jsOptionsStreamInfo - { - bool DeletedDetails; ///< Get the list of deleted message sequences. - const char *SubjectsFilter; ///< Get the list of subjects in this stream. - - } Info; ///< Optional stream information retrieval options. - - } Stream; ///< Optional stream options. + const char *Prefix; ///< JetStream prefix, default is "$JS.API" + const char *Domain; ///< Domain changes the domain part of JetSteam API prefix. + int64_t Wait; ///< Amount of time (in milliseconds) to wait for various JetStream API requests, default is 5000 ms (5 seconds). + jsOptionsPublishAsync PublishAsync; ///< extra options for #js_PublishAsync + jsOptionsPullSubscribeAsync PullSubscribeAsync; ///< extra options for #js_PullSubscribeAsync + jsOptionsStream Stream; ///< Optional stream options. } jsOptions; diff --git a/test/check_cpp/CMakeLists.txt b/test/check_cpp/CMakeLists.txt new file mode 100644 index 00000000..3df4db4d --- /dev/null +++ b/test/check_cpp/CMakeLists.txt @@ -0,0 +1,25 @@ +if(NOT BUILD_TESTING) + return() +endif() + +if(NOT NATS_BUILD_LIB_STATIC) + MESSAGE(FATAL_ERROR + "Building tests require static library, or run CMake with -DBUILD_TESTING=OFF") + return() +endif() + +if(MSVC) + set_source_files_properties(test.c PROPERTIES COMPILE_FLAGS "/w") +endif() + +# We need this to build the test program +include_directories(${PROJECT_SOURCE_DIR}/src) + +if(NATS_BUILD_WITH_TLS) + include_directories(${OPENSSL_INCLUDE_DIR}) +endif(NATS_BUILD_WITH_TLS) + +# Build the test program +add_executable(check_cpp check_cpp.cpp) + +target_link_libraries(check_cpp nats_static ${NATS_EXTRA_LIB}) diff --git a/test/check_cpp/check_cpp.cpp b/test/check_cpp/check_cpp.cpp new file mode 100644 index 00000000..985bf456 --- /dev/null +++ b/test/check_cpp/check_cpp.cpp @@ -0,0 +1,29 @@ +// Copyright 2017-2025 The NATS Authors +// Licensed 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 +#include + +// Check C++ compiler compatibility of structs in +// natsp.h to avoid incomplete type errors such as C2079. +#include + +int main(int argc, char **argv) +{ + // jsOptionsPullSubscribeAsync opts should be accessible + jsFetch fetch; + fetch.opts.Timeout = 1; + + std::cout << "OK" << std::endl; + return 0; +}