From 0c84a63991cfcea6adf22255759329567d9f7a85 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Tue, 19 Mar 2024 16:42:21 +0200 Subject: [PATCH 01/60] add first working UT for shutdown sequence --- groups/ntc/ntcr/ntcr_streamsocket.cpp | 4 +- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 1020 ++++++++++++++++++++++- 2 files changed, 1022 insertions(+), 2 deletions(-) diff --git a/groups/ntc/ntcr/ntcr_streamsocket.cpp b/groups/ntc/ntcr/ntcr_streamsocket.cpp index 0ce39e64..d04f8865 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.cpp @@ -1649,7 +1649,9 @@ void StreamSocket::privateFailConnectPart2( this->privateRetryConnect(self); } - this->moveAndExecute(&d_deferredCalls, ntci::Executor::Functor()); + if (!d_deferredCalls.empty()) { + this->moveAndExecute(&d_deferredCalls, ntci::Executor::Functor()); + } d_deferredCalls.clear(); if (lock) { diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index 258e2b0e..66902bb5 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -284,7 +284,7 @@ ntsa::Endpoint EndpointUtil::any(ntsa::Transport::Value transport) break; case ntsa::Transport::e_LOCAL_STREAM: case ntsa::Transport::e_LOCAL_DATAGRAM: { - ntsa::LocalName localName; + ntsa::LocalName localName; const ntsa::Error error = ntsa::LocalName::generateUnique(&localName); BSLS_ASSERT_OPT(!error); @@ -1370,6 +1370,914 @@ void variation(const test::Parameters& parameters) NTCCFG_BIND_PLACEHOLDER_3)); } +namespace mock { + +#define UNEXPECTED_CALL(unused) NTCCFG_TEST_TRUE(false && "unexpected call") + +class ResolverMock : public ntci::Resolver +{ + public: + void execute(const Functor& functor) override + { + UNEXPECTED_CALL(); + } + void moveAndExecute(FunctorSequence* functorSequence, + const Functor& functor) override + { + UNEXPECTED_CALL(); + } + const bsl::shared_ptr& strand() const override + { + UNEXPECTED_CALL(); + return dummyStrand; + } + ntsa::Error start() override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + void shutdown() override + { + UNEXPECTED_CALL(); + } + void linger() override + { + UNEXPECTED_CALL(); + } + ntsa::Error setIpAddress( + const bslstl::StringRef& domainName, + const bsl::vector& ipAddressList) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error addIpAddress( + const bslstl::StringRef& domainName, + const bsl::vector& ipAddressList) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error addIpAddress(const bslstl::StringRef& domainName, + const ntsa::IpAddress& ipAddress) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error setPort(const bslstl::StringRef& serviceName, + const bsl::vector& portList, + ntsa::Transport::Value transport) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error addPort(const bslstl::StringRef& serviceName, + const bsl::vector& portList, + ntsa::Transport::Value transport) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error addPort(const bslstl::StringRef& serviceName, + ntsa::Port port, + ntsa::Transport::Value transport) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error setLocalIpAddress( + const bsl::vector& ipAddressList) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error setHostname(const bsl::string& name) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error setHostnameFullyQualified(const bsl::string& name) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error getIpAddress( + const bslstl::StringRef& domainName, + const ntca::GetIpAddressOptions& options, + const ntci::GetIpAddressCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error getDomainName( + const ntsa::IpAddress& ipAddress, + const ntca::GetDomainNameOptions& options, + const ntci::GetDomainNameCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error getPort(const bslstl::StringRef& serviceName, + const ntca::GetPortOptions& options, + const ntci::GetPortCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error getServiceName( + ntsa::Port port, + const ntca::GetServiceNameOptions& options, + const ntci::GetServiceNameCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error getEndpoint(const bslstl::StringRef& text, + const ntca::GetEndpointOptions& options, + const ntci::GetEndpointCallback& callback) override + { + if (d_getEndpoint_error.isNull()) { + UNEXPECTED_CALL(); + } + if (d_getEndpoint_text.has_value()) { + NTCCFG_TEST_EQ(text, d_getEndpoint_text.value()); + d_getEndpoint_text.reset(); + } + if (d_getEndpoint_options.has_value()) { + NTCCFG_TEST_EQ(options, d_getEndpoint_options.value()); + d_getEndpoint_options.reset(); + } + NTCCFG_TEST_FALSE(d_getEndpoint_callback.has_value()); + d_getEndpoint_callback = callback; + + const auto res = d_getEndpoint_error.value(); + d_getEndpoint_error.reset(); + return res; + } + ntsa::Error getLocalIpAddress( + bsl::vector* result, + const ntsa::IpAddressOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error getHostname(bsl::string* result) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error getHostnameFullyQualified(bsl::string* result) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + bsl::shared_ptr createStrand( + bslma::Allocator* basicAllocator) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createTimer( + const ntca::TimerOptions& options, + const bsl::shared_ptr& session, + bslma::Allocator* basicAllocator) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createTimer( + const ntca::TimerOptions& options, + const ntci::TimerCallback& callback, + bslma::Allocator* basicAllocator) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsls::TimeInterval currentTime() const override + { + UNEXPECTED_CALL(); + return bsls::TimeInterval(); + } + + // auxilary functions + void set_getEndpoint_WillOnceReturn( + const bdlb::NullableValue& text, + const bdlb::NullableValue& options, + ntsa::Error error) + { + d_getEndpoint_text = text; + d_getEndpoint_options = options; + d_getEndpoint_error = error; + } + + private: + bsl::shared_ptr dummyStrand; + + bdlb::NullableValue d_getEndpoint_text; + bdlb::NullableValue d_getEndpoint_options; + bdlb::NullableValue d_getEndpoint_callback; + bdlb::NullableValue d_getEndpoint_error; +}; + +class BufferFactoryMock : public bdlbb::BlobBufferFactory +{ + public: + void allocate(bdlbb::BlobBuffer* buffer) override + { + UNEXPECTED_CALL(); + } +}; + +class StreamSocketMock : public ntsi::StreamSocket +{ + public: + ntsa::Handle handle() const override + { + UNEXPECTED_CALL(); + return 0; + } + ntsa::Error open(ntsa::Transport::Value transport) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error acquire(ntsa::Handle handle) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Handle release() override + { + UNEXPECTED_CALL(); + return 0; + } +}; + +class DataPoolMock : public ntci::DataPool +{ + public: + bsl::shared_ptr createIncomingData() override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createOutgoingData() override + { + if (d_outgoingData.isNull()) { + UNEXPECTED_CALL(); + } + return d_outgoingData.value(); + } + bsl::shared_ptr createIncomingBlob() override + { + if (d_incomingBlobBuffer.isNull()) { + UNEXPECTED_CALL(); + } + return d_incomingBlobBuffer.value(); + } + bsl::shared_ptr createOutgoingBlob() override + { + if (d_outgoingBlobBuffer.isNull()) { + UNEXPECTED_CALL(); + } + return d_outgoingBlobBuffer.value(); + } + void createIncomingBlobBuffer(bdlbb::BlobBuffer* blobBuffer) override + { + UNEXPECTED_CALL(); + } + void createOutgoingBlobBuffer(bdlbb::BlobBuffer* blobBuffer) override + { + UNEXPECTED_CALL(); + } + const bsl::shared_ptr& incomingBlobBufferFactory() + const override + { + UNEXPECTED_CALL(); + return dummyBlobBufferFactory; + } + const bsl::shared_ptr& outgoingBlobBufferFactory() + const override + { + UNEXPECTED_CALL(); + return dummyBlobBufferFactory; + } + + // auxilary functions + + void set_createIncomingBlobBuffer_WillAlwaysReturn( + const bsl::shared_ptr& blob) + { + d_incomingBlobBuffer = blob; + } + + void set_createOutgoingBlobBuffer_WillAlwaysReturn( + const bsl::shared_ptr& blob) + { + d_outgoingBlobBuffer = blob; + } + + void set_createOutgoingData_WillAlwaysReturn( + bsl::shared_ptr data) + { + d_outgoingData = data; + } + + private: + bsl::shared_ptr dummyBlobBufferFactory; + bdlb::NullableValue > d_incomingBlobBuffer; + bdlb::NullableValue > d_outgoingBlobBuffer; + bdlb::NullableValue > d_outgoingData; +}; + +class ReactorMock : public ntci::Reactor +{ + public: + bsl::shared_ptr createDatagramSocket( + const ntca::DatagramSocketOptions& options, + bslma::Allocator* basicAllocator) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createIncomingData() override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createOutgoingData() override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createIncomingBlob() override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createOutgoingBlob() override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + void createIncomingBlobBuffer(bdlbb::BlobBuffer* blobBuffer) override + { + UNEXPECTED_CALL(); + } + void createOutgoingBlobBuffer(bdlbb::BlobBuffer* blobBuffer) override + { + UNEXPECTED_CALL(); + } + const bsl::shared_ptr& incomingBlobBufferFactory() + const override + { + if (d_incomingBlobBufferFactory.isNull()) { + UNEXPECTED_CALL(); + } + return d_incomingBlobBufferFactory.value(); + } + const bsl::shared_ptr& outgoingBlobBufferFactory() + const override + { + if (d_outgoingBlobBufferFactory.isNull()) { + UNEXPECTED_CALL(); + } + return d_outgoingBlobBufferFactory.value(); + } + ntci::Waiter registerWaiter( + const ntca::WaiterOptions& waiterOptions) override + { + UNEXPECTED_CALL(); + return nullptr; + } + void deregisterWaiter(ntci::Waiter waiter) override + { + UNEXPECTED_CALL(); + } + void run(ntci::Waiter waiter) override + { + UNEXPECTED_CALL(); + } + void poll(ntci::Waiter waiter) override + { + UNEXPECTED_CALL(); + } + void interruptOne() override + { + UNEXPECTED_CALL(); + } + void interruptAll() override + { + UNEXPECTED_CALL(); + } + void stop() override + { + UNEXPECTED_CALL(); + } + void restart() override + { + UNEXPECTED_CALL(); + } + void execute(const Functor& functor) override + { + if (!d_executeExpected) { + UNEXPECTED_CALL(); + } + d_executeExpected = false; + NTCCFG_TEST_FALSE(d_execute_functor.has_value()); + d_execute_functor = functor; + } + void moveAndExecute(FunctorSequence* functorSequence, + const Functor& functor) override + { + UNEXPECTED_CALL(); + } + bsl::shared_ptr createListenerSocket( + const ntca::ListenerSocketOptions& options, + bslma::Allocator* basicAllocator) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + ntsa::Error attachSocket( + const bsl::shared_ptr& socket) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error attachSocket(ntsa::Handle handle) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error showReadable( + const bsl::shared_ptr& socket, + const ntca::ReactorEventOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error showReadable( + ntsa::Handle handle, + const ntca::ReactorEventOptions& options, + const ntci::ReactorEventCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error showWritable( + const bsl::shared_ptr& socket, + const ntca::ReactorEventOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error showWritable( + ntsa::Handle handle, + const ntca::ReactorEventOptions& options, + const ntci::ReactorEventCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error showError(const bsl::shared_ptr& socket, + const ntca::ReactorEventOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error showError(ntsa::Handle handle, + const ntca::ReactorEventOptions& options, + const ntci::ReactorEventCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error hideReadable( + const bsl::shared_ptr& socket) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error hideReadable(ntsa::Handle handle) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error hideWritable( + const bsl::shared_ptr& socket) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error hideWritable(ntsa::Handle handle) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error hideError( + const bsl::shared_ptr& socket) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error hideError(ntsa::Handle handle) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error detachSocket( + const bsl::shared_ptr& socket) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error detachSocket(ntsa::Handle handle) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error closeAll() override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + void incrementLoad(const ntca::LoadBalancingOptions& options) override + { + UNEXPECTED_CALL(); + } + void decrementLoad(const ntca::LoadBalancingOptions& options) override + { + UNEXPECTED_CALL(); + } + void drainFunctions() override + { + UNEXPECTED_CALL(); + } + void clearFunctions() override + { + UNEXPECTED_CALL(); + } + void clearTimers() override + { + UNEXPECTED_CALL(); + } + void clearSockets() override + { + UNEXPECTED_CALL(); + } + void clear() override + { + UNEXPECTED_CALL(); + } + size_t numSockets() const override + { + UNEXPECTED_CALL(); + return 0; + } + size_t maxSockets() const override + { + UNEXPECTED_CALL(); + return 0; + } + size_t numTimers() const override + { + UNEXPECTED_CALL(); + return 0; + } + size_t maxTimers() const override + { + UNEXPECTED_CALL(); + return 0; + } + bool autoAttach() const override + { + UNEXPECTED_CALL(); + return false; + } + bool autoDetach() const override + { + UNEXPECTED_CALL(); + return false; + } + bool oneShot() const override + { + if (d_oneShot.isNull()) { + UNEXPECTED_CALL(); + } + return d_oneShot.value(); + } + ntca::ReactorEventTrigger::Value trigger() const override + { + UNEXPECTED_CALL(); + return ntca::ReactorEventTrigger::e_LEVEL; + } + size_t load() const override + { + UNEXPECTED_CALL(); + return 0; + } + bslmt::ThreadUtil::Handle threadHandle() const override + { + UNEXPECTED_CALL(); + return BloombergLP::bslmt::ThreadUtil::Handle(); + } + size_t threadIndex() const override + { + UNEXPECTED_CALL(); + return 0; + } + bool empty() const override + { + UNEXPECTED_CALL(); + return false; + } + const bsl::shared_ptr& dataPool() const override + { + if (d_dataPool.isNull()) { + UNEXPECTED_CALL(); + } + return d_dataPool.value(); + } + bool supportsOneShot(bool oneShot) const override + { + UNEXPECTED_CALL(); + return false; + } + bool supportsTrigger( + ntca::ReactorEventTrigger::Value trigger) const override + { + UNEXPECTED_CALL(); + return false; + } + bsl::shared_ptr acquireReactor( + const ntca::LoadBalancingOptions& options) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + void releaseReactor(const bsl::shared_ptr& reactor, + const ntca::LoadBalancingOptions& options) override + { + UNEXPECTED_CALL(); + } + bool acquireHandleReservation() override + { + UNEXPECTED_CALL(); + return false; + } + void releaseHandleReservation() override + { + UNEXPECTED_CALL(); + } + size_t numReactors() const override + { + UNEXPECTED_CALL(); + return 0; + } + size_t numThreads() const override + { + UNEXPECTED_CALL(); + return 0; + } + size_t minThreads() const override + { + UNEXPECTED_CALL(); + return 0; + } + size_t maxThreads() const override + { + if (d_maxThreads.isNull()) { + UNEXPECTED_CALL(); + } + return d_maxThreads.value(); + } + bsl::shared_ptr createStrand( + bslma::Allocator* basicAllocator) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createStreamSocket( + const ntca::StreamSocketOptions& options, + bslma::Allocator* basicAllocator) override + { + UNEXPECTED_CALL(); + return bsl::shared_ptr(); + } + bsl::shared_ptr createTimer( + const ntca::TimerOptions& options, + const bsl::shared_ptr& session, + bslma::Allocator* basicAllocator) override + { + if (d_timer.isNull()) { + UNEXPECTED_CALL(); + } + const auto timer = d_timer.value(); + d_timer->clear(); + return timer; + } + bsl::shared_ptr createTimer( + const ntca::TimerOptions& options, + const ntci::TimerCallback& callback, + bslma::Allocator* basicAllocator) override + { + if (d_timer.isNull()) { + UNEXPECTED_CALL(); + } + + NTCCFG_TEST_TRUE(d_timerCallback.isNull()); + d_timerCallback = callback; + + const auto timer = d_timer.value(); + d_timer.reset(); + return timer; + } + const bsl::shared_ptr& strand() const override + { + UNEXPECTED_CALL(); + return dummyStrand; + } + bsls::TimeInterval currentTime() const override + { + UNEXPECTED_CALL(); + return bsls::TimeInterval(); + } + + // auxilary methods + void set_dataPool_WillAlwaysReturn( + const bsl::shared_ptr& dataPool) + { + d_dataPool = dataPool; + } + + void set_outgoingBlobBufferFactory_WillAlwaysReturn( + bsl::shared_ptr bufferFactory) + { + d_outgoingBlobBufferFactory = bufferFactory; + } + + void set_incomingBlobBufferFactory_WillAlwaysReturn( + bsl::shared_ptr bufferFactory) + { + d_incomingBlobBufferFactory = bufferFactory; + } + + void set_oneShot_WillAlwaysReturn(bool flag) + { + d_oneShot = flag; + } + + void set_maxThreads_WillAlwaysReturn(size_t val) + { + d_maxThreads = val; + } + + void set_createTimer_WillOnceReturn( + const bsl::shared_ptr& timer) + { + d_timer = timer; + } + + void set_execute_expectedOnce() + { + d_executeExpected = true; + } + + ntci::TimerCallback extract_timerCallback() + { + NTCCFG_TEST_TRUE(d_timerCallback.has_value()); + const auto res = d_timerCallback.value(); + d_timerCallback.reset(); + return res; + } + + ntci::Reactor::Functor extract_execute_functor() + { + ntci::Reactor::Functor res = d_execute_functor.value(); + d_execute_functor.reset(); + return res; + } + + private: + bdlb::NullableValue > + d_incomingBlobBufferFactory; + bdlb::NullableValue > + d_outgoingBlobBufferFactory; + bsl::shared_ptr dummyStrand; + bdlb::NullableValue > d_dataPool; + bdlb::NullableValue d_oneShot; + bdlb::NullableValue d_maxThreads; + bdlb::NullableValue > d_timer; + bdlb::NullableValue d_timerCallback; + bool d_executeExpected; + bdlb::NullableValue d_execute_functor; +}; + +class TimerMock : public ntci::Timer +{ + public: + ntsa::Error schedule(const bsls::TimeInterval& deadline, + const bsls::TimeInterval& period) override + { + if (d_scheduleReturn_error.isNull()) { + UNEXPECTED_CALL(); + } + if (d_scheduleArg_deadline.has_value()) { + NTCCFG_TEST_EQ(deadline, d_scheduleArg_deadline.value()); + d_scheduleArg_deadline.reset(); + } + if (d_scheduleArg_period.has_value()) { + NTCCFG_TEST_EQ(period, d_scheduleArg_period.value()); + d_scheduleArg_period.reset(); + } + const auto error = d_scheduleReturn_error.value(); + d_scheduleReturn_error.reset(); + + return error; + } + ntsa::Error cancel() override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error close() override + { + if (d_close_error.isNull()) { + UNEXPECTED_CALL(); + } + const auto res = d_close_error.value(); + d_close_error.reset(); + return res; + } + void arrive(const bsl::shared_ptr& self, + const bsls::TimeInterval& now, + const bsls::TimeInterval& deadline) override + { + UNEXPECTED_CALL(); + } + void* handle() const override + { + UNEXPECTED_CALL(); + return nullptr; + } + int id() const override + { + UNEXPECTED_CALL(); + return 0; + } + bool oneShot() const override + { + UNEXPECTED_CALL(); + return false; + } + bslmt::ThreadUtil::Handle threadHandle() const override + { + UNEXPECTED_CALL(); + return BloombergLP::bslmt::ThreadUtil::Handle(); + } + size_t threadIndex() const override + { + UNEXPECTED_CALL(); + return 0; + } + const bsl::shared_ptr& strand() const override + { + UNEXPECTED_CALL(); + return dummyStrand; + } + bsls::TimeInterval currentTime() const override + { + UNEXPECTED_CALL(); + return bsls::TimeInterval(); + } + + void set_schedule_willOnceReturn( + const bdlb::NullableValue& deadline, + const bdlb::NullableValue& period, + ntsa::Error error) + { + d_scheduleArg_deadline = deadline; + d_scheduleArg_period = period; + d_scheduleReturn_error = error; + } + + void set_close_WillOnceReturn(const ntsa::Error& error) + { + d_close_error = error; + } + + private: + bsl::shared_ptr dummyStrand; + + bdlb::NullableValue d_scheduleArg_deadline; + bdlb::NullableValue d_scheduleArg_period; + bdlb::NullableValue d_scheduleReturn_error; + bdlb::NullableValue d_close_error; +}; + +} // close namespace mock + } // close namespace test NTCCFG_TEST_CASE(1) @@ -3347,6 +4255,114 @@ NTCCFG_TEST_CASE(21) #endif } +NTCCFG_TEST_CASE(22) +{ + NTCI_LOG_CONTEXT(); + + ntccfg::TestAllocator ta; + { + NTCI_LOG_DEBUG("Fixture setup, socket creation..."); + + bdlb::NullableValue connectResult; + + bsl::shared_ptr nullPool; + bsl::shared_ptr nullMetrics; + bsl::shared_ptr nullBlob; + bsl::shared_ptr nullStrand; + + bsl::shared_ptr dummyData; + dummyData.createInplace(&ta); + + bsl::shared_ptr resolverMock; + resolverMock.createInplace(&ta); + + bsl::shared_ptr reactorMock; + reactorMock.createInplace(&ta); + + bsl::shared_ptr socketMock; + socketMock.createInplace(&ta); + + bsl::shared_ptr dataPoolMock; + dataPoolMock.createInplace(&ta); + reactorMock->set_dataPool_WillAlwaysReturn(dataPoolMock); + + bsl::shared_ptr bufferFactoryMock; + bufferFactoryMock.createInplace(&ta); + reactorMock->set_outgoingBlobBufferFactory_WillAlwaysReturn( + bufferFactoryMock); + reactorMock->set_incomingBlobBufferFactory_WillAlwaysReturn( + bufferFactoryMock); + + reactorMock->set_oneShot_WillAlwaysReturn(false); + reactorMock->set_maxThreads_WillAlwaysReturn(1); + + dataPoolMock->set_createIncomingBlobBuffer_WillAlwaysReturn(nullBlob); + dataPoolMock->set_createOutgoingBlobBuffer_WillAlwaysReturn(nullBlob); + dataPoolMock->set_createOutgoingData_WillAlwaysReturn(dummyData); + + const ntca::StreamSocketOptions options; + + ntcr::StreamSocket socket(options, + resolverMock, + reactorMock, + nullPool, + nullMetrics, + &ta); + + NTCI_LOG_DEBUG("Connection initiation..."); + + bsl::shared_ptr connectRetryTimerMock; + connectRetryTimerMock.createInplace(&ta); + reactorMock->set_createTimer_WillOnceReturn(connectRetryTimerMock); + + connectRetryTimerMock->set_schedule_willOnceReturn( + bdlb::NullOptType::makeInitialValue(), + bdlb::NullOptType::makeInitialValue(), + ntsa::Error()); + + const ntci::ConnectFunction connectCallback = + [&connectResult](const bsl::shared_ptr& connector, + const ntca::ConnectEvent& event) { + NTCCFG_TEST_FALSE(connectResult.has_value()); + connectResult = event; + }; + + const ntca::ConnectOptions connectOptions; + + const bsl::string epName = "unreachable.bbg.com"; + + socket.connect(epName, connectOptions, connectCallback); + + NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); + + resolverMock->set_getEndpoint_WillOnceReturn( + epName, + bdlb::NullOptType::makeInitialValue(), + ntsa::Error()); + + const auto timerCallback = reactorMock->extract_timerCallback(); + ntca::TimerEvent timerEvent; + timerEvent.setType(ntca::TimerEventType::e_DEADLINE); + timerCallback(connectRetryTimerMock, timerEvent, nullStrand); + + NTCI_LOG_DEBUG("Shutdown socket while it is waiting for remote " + "endpoint resolution"); + + connectRetryTimerMock->set_close_WillOnceReturn(ntsa::Error()); + reactorMock->set_execute_expectedOnce(); + + socket.shutdown(ntsa::ShutdownType::e_BOTH, + ntsa::ShutdownMode::e_GRACEFUL); + + const auto callback = reactorMock->extract_execute_functor(); + callback(); + NTCCFG_TEST_TRUE(connectResult.has_value()); + NTCCFG_TEST_EQ(connectResult.value().type(), + ntca::ConnectEventType::e_ERROR); + } + NTCCFG_TEST_ASSERT(ta.numBlocksInUse() == 0); +} + NTCCFG_TEST_DRIVER { NTCCFG_TEST_REGISTER(1); @@ -3376,5 +4392,7 @@ NTCCFG_TEST_DRIVER NTCCFG_TEST_REGISTER(20); NTCCFG_TEST_REGISTER(21); + + NTCCFG_TEST_REGISTER(22); } NTCCFG_TEST_DRIVER_END; From d3b20a5f455645c2a2958270eab7ea5ac0ebc0a9 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Wed, 20 Mar 2024 13:20:45 +0200 Subject: [PATCH 02/60] Add TC23 --- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 261 +++++++++++++++++++++++- 1 file changed, 254 insertions(+), 7 deletions(-) diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index 66902bb5..289e56c4 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1802,8 +1802,16 @@ class ReactorMock : public ntci::Reactor ntsa::Error attachSocket( const bsl::shared_ptr& socket) override { - UNEXPECTED_CALL(); - return ntsa::Error(); + if (d_attachSocket_result.isNull()) { + UNEXPECTED_CALL(); + } + if (d_attachSocket_socket.has_value()) { + NTCCFG_TEST_EQ(socket, d_attachSocket_socket.value()); + d_attachSocket_socket.reset(); + } + const auto res = d_attachSocket_result.value(); + d_attachSocket_result.reset(); + return res; } ntsa::Error attachSocket(ntsa::Handle handle) override { @@ -1829,8 +1837,18 @@ class ReactorMock : public ntci::Reactor const bsl::shared_ptr& socket, const ntca::ReactorEventOptions& options) override { - UNEXPECTED_CALL(); - return ntsa::Error(); + if (d_showWritable_result.isNull()) { + UNEXPECTED_CALL(); + } + + if (d_showWritable_socket.has_value()) { + NTCCFG_TEST_EQ(socket, d_showWritable_socket.value()); + d_showWritable_socket.reset(); + } + + const auto res = d_showWritable_result.value(); + d_showWritable_result.reset(); + return res; } ntsa::Error showWritable( ntsa::Handle handle, @@ -1897,6 +1915,41 @@ class ReactorMock : public ntci::Reactor UNEXPECTED_CALL(); return ntsa::Error(); } + ntsa::Error detachSocket( + const bsl::shared_ptr& socket, + const ntci::SocketDetachedCallback& callback) override + { + if (d_detachSocket_result.isNull()) { + UNEXPECTED_CALL(); + } + + if (d_detachSocket_arg2.has_value()) { + NTCCFG_TEST_EQ(callback, d_detachSocket_arg2.value()); + d_detachSocket_arg2.reset(); + } + else { + d_detachSocket_arg2 = callback; + } + + if (d_detachSocket_arg1.has_value()) { + NTCCFG_TEST_EQ(socket, d_detachSocket_arg1.value()); + d_detachSocket_arg1.reset(); + } + else { + d_detachSocket_arg1 = socket; //TODO: how to clean it then? + } + + const auto result = d_detachSocket_result.value(); + d_detachSocket_result.reset(); + return result; + } + ntsa::Error detachSocket( + ntsa::Handle handle, + const ntci::SocketDetachedCallback& callback) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } ntsa::Error closeAll() override { UNEXPECTED_CALL(); @@ -2023,12 +2076,16 @@ class ReactorMock : public ntci::Reactor } bool acquireHandleReservation() override { - UNEXPECTED_CALL(); - return false; + if (d_aquireHandleReservation.isNull()) { + UNEXPECTED_CALL(); + } + return d_aquireHandleReservation.value(); } void releaseHandleReservation() override { - UNEXPECTED_CALL(); + if (!d_releaseHandleReservation) { + UNEXPECTED_CALL(); + } } size_t numReactors() const override { @@ -2144,6 +2201,51 @@ class ReactorMock : public ntci::Reactor d_executeExpected = true; } + void set_aquireHandleReservation_WillAlwaysReturn(bool flag) + { + d_aquireHandleReservation = flag; + } + + void set_releaseHandleReservation_WillAlwaysReturn() + { + d_releaseHandleReservation = true; + } + + void set_attachSocket_WillOnceReturn( + const bdlb::NullableValue >& + socket, + const ntsa::Error& result) + { + NTCCFG_TEST_TRUE(d_attachSocket_result.isNull()); + NTCCFG_TEST_TRUE(d_attachSocket_socket.isNull()); + + d_attachSocket_result = result; + d_attachSocket_socket = socket; + } + + void set_showWritable_WillOnceReturn( + const bdlb::NullableValue >& + socket, + const ntsa::Error& error) + { + NTCCFG_TEST_TRUE(d_showWritable_result.isNull()); + NTCCFG_TEST_TRUE(d_showWritable_socket.isNull()); + + d_showWritable_result = error; + d_showWritable_socket = socket; + } + + void set_detachSocket_WillOnceReturn( + const bdlb::NullableValue >& + socket, + const bdlb::NullableValue& callback, + const ntsa::Error& result) + { + d_detachSocket_result = result; + d_detachSocket_arg1 = socket; + d_detachSocket_arg2 = callback; + } + ntci::TimerCallback extract_timerCallback() { NTCCFG_TEST_TRUE(d_timerCallback.has_value()); @@ -2159,6 +2261,14 @@ class ReactorMock : public ntci::Reactor return res; } + ntci::SocketDetachedCallback extract_detachCallback() + { + NTCCFG_TEST_TRUE(d_detachSocket_arg2.has_value()); + const auto res = d_detachSocket_arg2.value(); + d_detachSocket_arg2.reset(); + return res; + } + private: bdlb::NullableValue > d_incomingBlobBufferFactory; @@ -2172,6 +2282,21 @@ class ReactorMock : public ntci::Reactor bdlb::NullableValue d_timerCallback; bool d_executeExpected; bdlb::NullableValue d_execute_functor; + bdlb::NullableValue d_aquireHandleReservation; + bool d_releaseHandleReservation; + + bdlb::NullableValue > + d_attachSocket_socket; + bdlb::NullableValue d_attachSocket_result; + + bdlb::NullableValue > + d_showWritable_socket; + bdlb::NullableValue d_showWritable_result; + + bdlb::NullableValue d_detachSocket_result; + bdlb::NullableValue > + d_detachSocket_arg1; + bdlb::NullableValue d_detachSocket_arg2; }; class TimerMock : public ntci::Timer @@ -4363,6 +4488,127 @@ NTCCFG_TEST_CASE(22) NTCCFG_TEST_ASSERT(ta.numBlocksInUse() == 0); } +NTCCFG_TEST_CASE(23) +{ + NTCI_LOG_CONTEXT(); + + ntccfg::TestAllocator ta; + { + NTCI_LOG_DEBUG("Fixture setup, socket creation..."); + + bdlb::NullableValue connectResult; + + bsl::shared_ptr nullPool; + bsl::shared_ptr nullMetrics; + bsl::shared_ptr nullBlob; + bsl::shared_ptr nullStrand; + + bsl::shared_ptr dummyData; + dummyData.createInplace(&ta); + + bsl::shared_ptr resolverMock; + resolverMock.createInplace(&ta); + + bsl::shared_ptr reactorMock; + reactorMock.createInplace(&ta); + + bsl::shared_ptr socketMock; + socketMock.createInplace(&ta); + + bsl::shared_ptr dataPoolMock; + dataPoolMock.createInplace(&ta); + reactorMock->set_dataPool_WillAlwaysReturn(dataPoolMock); + + bsl::shared_ptr bufferFactoryMock; + bufferFactoryMock.createInplace(&ta); + reactorMock->set_outgoingBlobBufferFactory_WillAlwaysReturn( + bufferFactoryMock); + reactorMock->set_incomingBlobBufferFactory_WillAlwaysReturn( + bufferFactoryMock); + + reactorMock->set_oneShot_WillAlwaysReturn(false); + reactorMock->set_maxThreads_WillAlwaysReturn(1); + + dataPoolMock->set_createIncomingBlobBuffer_WillAlwaysReturn(nullBlob); + dataPoolMock->set_createOutgoingBlobBuffer_WillAlwaysReturn(nullBlob); + dataPoolMock->set_createOutgoingData_WillAlwaysReturn(dummyData); + + const ntca::StreamSocketOptions options; + + bsl::shared_ptr socket; + socket.createInplace(&ta, + options, + resolverMock, + reactorMock, + nullPool, + nullMetrics, + &ta); + + NTCI_LOG_DEBUG("Connection initiation..."); + + bsl::shared_ptr connectRetryTimerMock; + connectRetryTimerMock.createInplace(&ta); + reactorMock->set_createTimer_WillOnceReturn(connectRetryTimerMock); + + connectRetryTimerMock->set_schedule_willOnceReturn( + bdlb::NullOptType::makeInitialValue(), + bdlb::NullOptType::makeInitialValue(), + ntsa::Error()); + + const ntci::ConnectFunction connectCallback = + [&connectResult](const bsl::shared_ptr& connector, + const ntca::ConnectEvent& event) { + NTCCFG_TEST_FALSE(connectResult.has_value()); + connectResult = event; + }; + + const ntca::ConnectOptions connectOptions; + + const ntsa::Endpoint ep{"127.0.0.1:1234"}; + + socket->connect(ep, connectOptions, connectCallback); + + NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); + + reactorMock->set_aquireHandleReservation_WillAlwaysReturn(true); + reactorMock->set_releaseHandleReservation_WillAlwaysReturn(); + reactorMock->set_attachSocket_WillOnceReturn(socket, ntsa::Error()); + reactorMock->set_showWritable_WillOnceReturn(socket, ntsa::Error()); + + const auto timerCallback = reactorMock->extract_timerCallback(); + ntca::TimerEvent timerEvent; + timerEvent.setType(ntca::TimerEventType::e_DEADLINE); + timerCallback(connectRetryTimerMock, timerEvent, nullStrand); + + NTCI_LOG_DEBUG( + "Shutdown socket while it is waiting for connection result"); + + connectRetryTimerMock->set_close_WillOnceReturn(ntsa::Error()); + + reactorMock->set_detachSocket_WillOnceReturn( + socket, + bdlb::NullOptType::makeInitialValue(), + ntsa::Error()); + + socket->shutdown(ntsa::ShutdownType::e_BOTH, + ntsa::ShutdownMode::e_GRACEFUL); + + const auto detachCallback = reactorMock->extract_detachCallback(); + NTCCFG_TEST_TRUE(detachCallback); + + reactorMock->set_execute_expectedOnce(); + detachCallback(nullStrand); + + const auto callback = reactorMock->extract_execute_functor(); + callback(); + + NTCCFG_TEST_TRUE(connectResult.has_value()); + NTCCFG_TEST_EQ(connectResult.value().type(), + ntca::ConnectEventType::e_ERROR); + } + NTCCFG_TEST_ASSERT(ta.numBlocksInUse() == 0); +} + NTCCFG_TEST_DRIVER { NTCCFG_TEST_REGISTER(1); @@ -4394,5 +4640,6 @@ NTCCFG_TEST_DRIVER NTCCFG_TEST_REGISTER(21); NTCCFG_TEST_REGISTER(22); + NTCCFG_TEST_REGISTER(23); } NTCCFG_TEST_DRIVER_END; From 25300389206f889d4563eb8baf82959b08b09cf7 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Wed, 20 Mar 2024 13:43:44 +0200 Subject: [PATCH 03/60] renaming --- groups/ntc/ntcd/ntcd_machine.cpp | 4 +- groups/ntc/ntco/ntco_epoll.cpp | 32 +-- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 309 ++++++++++++------------ 3 files changed, 176 insertions(+), 169 deletions(-) diff --git a/groups/ntc/ntcd/ntcd_machine.cpp b/groups/ntc/ntcd/ntcd_machine.cpp index cbdd2f52..841e7f39 100644 --- a/groups/ntc/ntcd/ntcd_machine.cpp +++ b/groups/ntc/ntcd/ntcd_machine.cpp @@ -4021,7 +4021,7 @@ bsl::size_t Monitor::process(bsl::vector* result) // MRM #if 0 - if (entry->d_oneShot) { + if (entry->d_oneShot_result) { entry->d_wantReadable = false; } #endif @@ -4052,7 +4052,7 @@ bsl::size_t Monitor::process(bsl::vector* result) // MRM #if 0 - if (entry->d_oneShot) { + if (entry->d_oneShot_result) { entry->d_wantWritable = false; } #endif diff --git a/groups/ntc/ntco/ntco_epoll.cpp b/groups/ntc/ntco/ntco_epoll.cpp index 30664419..b33a41b8 100644 --- a/groups/ntc/ntco/ntco_epoll.cpp +++ b/groups/ntc/ntco/ntco_epoll.cpp @@ -101,7 +101,7 @@ BSLS_IDENT_RCSID(ntco_epoll_cpp, "$Id$ $CSID$") #define NTCO_EPOLL_LOG_WAIT_RESULT_OR_TIMEOUT(numEvents, results) \ do { \ - if (numEvents == 1 && results[0].data.fd == d_timer) { \ + if (numEvents == 1 && results[0].data.fd == d_timer_result) { \ NTCO_EPOLL_LOG_WAIT_TIMEOUT(); \ } \ else { \ @@ -218,7 +218,7 @@ class Epoll : public ntci::Reactor, ntccfg::Object d_object; int d_epoll; - int d_timer; + int d_timer_result; bsls::AtomicBool d_timerPending; ntcs::RegistryEntryCatalog::EntryFunctor d_detachFunctor; ntcs::RegistryEntryCatalog d_registry; @@ -973,7 +973,7 @@ ntsa::Error Epoll::setTimer(const bsls::TimeInterval& absoluteTimeout) its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; - int rc = ::timerfd_settime(d_timer, TFD_TIMER_ABSTIME, &its, 0); + int rc = ::timerfd_settime(d_timer_result, TFD_TIMER_ABSTIME, &its, 0); if (rc != 0) { ntsa::Error error(errno); return error; @@ -988,7 +988,7 @@ ntsa::Error Epoll::ackTimer(bsl::size_t* numTimers) { bsl::uint64_t numExpirations = 0; ssize_t timerReadResult = - ::read(d_timer, &numExpirations, sizeof numExpirations); + ::read(d_timer_result, &numExpirations, sizeof numExpirations); if (NTCCFG_UNLIKELY(timerReadResult < 0)) { #if (EAGAIN == EWOULDBLOCK) @@ -1070,7 +1070,7 @@ Epoll::Epoll(const ntca::ReactorConfig& configuration, bslma::Allocator* basicAllocator) : d_object("ntco::Epoll") , d_epoll(-1) -, d_timer(-1) +, d_timer_result(-1) , d_timerPending(false) #if NTCCFG_PLATFORM_COMPILER_SUPPORTS_LAMDAS , d_detachFunctor([this](const auto& entry) { @@ -1235,18 +1235,18 @@ Epoll::Epoll(const ntca::ReactorConfig& configuration, #if NTCO_EPOLL_USE_TIMERFD if (d_config.maxThreads().value() == 1) { - d_timer = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC); - if (d_timer < 0) { + d_timer_result = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC); + if (d_timer_result < 0) { NTCCFG_ABORT(); } { ::epoll_event e; - e.data.fd = d_timer; + e.data.fd = d_timer_result; e.events = EPOLLIN; - int rc = ::epoll_ctl(d_epoll, EPOLL_CTL_ADD, d_timer, &e); + int rc = ::epoll_ctl(d_epoll, EPOLL_CTL_ADD, d_timer_result, &e); if (rc != 0) { NTCCFG_ABORT(); } @@ -1274,18 +1274,18 @@ Epoll::~Epoll() { ::epoll_event e; - e.data.fd = d_timer; + e.data.fd = d_timer_result; e.events = 0; - int rc = ::epoll_ctl(d_epoll, EPOLL_CTL_DEL, d_timer, &e); + int rc = ::epoll_ctl(d_epoll, EPOLL_CTL_DEL, d_timer_result, &e); if (rc != 0) { NTCCFG_ABORT(); } } - if (d_timer >= 0) { - ::close(d_timer); - d_timer = -1; + if (d_timer_result >= 0) { + ::close(d_timer_result); + d_timer_result = -1; } } @@ -2253,7 +2253,7 @@ void Epoll::run(ntci::Waiter waiter) #if NTCO_EPOLL_USE_TIMERFD - if (NTCCFG_UNLIKELY(e.data.fd == d_timer)) { + if (NTCCFG_UNLIKELY(e.data.fd == d_timer_result)) { ntsa::Error error = this->ackTimer(&numTimers); if (error) { NTCO_EPOLL_LOG_TIMER_ACK_FAILURE(error); @@ -2552,7 +2552,7 @@ void Epoll::poll(ntci::Waiter waiter) #if NTCO_EPOLL_USE_TIMERFD - if (NTCCFG_UNLIKELY(e.data.fd == d_timer)) { + if (NTCCFG_UNLIKELY(e.data.fd == d_timer_result)) { ntsa::Error error = this->ackTimer(&numTimers); if (error) { NTCO_EPOLL_LOG_TIMER_ACK_FAILURE(error); diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index 289e56c4..56342843 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1496,22 +1496,22 @@ class ResolverMock : public ntci::Resolver const ntca::GetEndpointOptions& options, const ntci::GetEndpointCallback& callback) override { - if (d_getEndpoint_error.isNull()) { + if (d_getEndpoint_result.isNull()) { UNEXPECTED_CALL(); } - if (d_getEndpoint_text.has_value()) { - NTCCFG_TEST_EQ(text, d_getEndpoint_text.value()); - d_getEndpoint_text.reset(); + if (d_getEndpoint_arg1.has_value()) { + NTCCFG_TEST_EQ(text, d_getEndpoint_arg1.value()); + d_getEndpoint_arg1.reset(); } - if (d_getEndpoint_options.has_value()) { - NTCCFG_TEST_EQ(options, d_getEndpoint_options.value()); - d_getEndpoint_options.reset(); + if (d_getEndpoint_arg2.has_value()) { + NTCCFG_TEST_EQ(options, d_getEndpoint_arg2.value()); + d_getEndpoint_arg2.reset(); } NTCCFG_TEST_FALSE(d_getEndpoint_callback.has_value()); d_getEndpoint_callback = callback; - const auto res = d_getEndpoint_error.value(); - d_getEndpoint_error.reset(); + const auto res = d_getEndpoint_result.value(); + d_getEndpoint_result.reset(); return res; } ntsa::Error getLocalIpAddress( @@ -1559,24 +1559,24 @@ class ResolverMock : public ntci::Resolver return bsls::TimeInterval(); } - // auxilary functions - void set_getEndpoint_WillOnceReturn( + // auxiliary functions + void expect_getEndpoint_WillOnceReturn( const bdlb::NullableValue& text, const bdlb::NullableValue& options, ntsa::Error error) { - d_getEndpoint_text = text; - d_getEndpoint_options = options; - d_getEndpoint_error = error; + d_getEndpoint_arg1 = text; + d_getEndpoint_arg2 = options; + d_getEndpoint_result = error; } private: bsl::shared_ptr dummyStrand; - bdlb::NullableValue d_getEndpoint_text; - bdlb::NullableValue d_getEndpoint_options; + bdlb::NullableValue d_getEndpoint_arg1; + bdlb::NullableValue d_getEndpoint_arg2; bdlb::NullableValue d_getEndpoint_callback; - bdlb::NullableValue d_getEndpoint_error; + bdlb::NullableValue d_getEndpoint_result; }; class BufferFactoryMock : public bdlbb::BlobBufferFactory @@ -1623,24 +1623,24 @@ class DataPoolMock : public ntci::DataPool } bsl::shared_ptr createOutgoingData() override { - if (d_outgoingData.isNull()) { + if (d_createOutgoingData_result.isNull()) { UNEXPECTED_CALL(); } - return d_outgoingData.value(); + return d_createOutgoingData_result.value(); } bsl::shared_ptr createIncomingBlob() override { - if (d_incomingBlobBuffer.isNull()) { + if (d_createIncomingBlobBuffer_result.isNull()) { UNEXPECTED_CALL(); } - return d_incomingBlobBuffer.value(); + return d_createIncomingBlobBuffer_result.value(); } bsl::shared_ptr createOutgoingBlob() override { - if (d_outgoingBlobBuffer.isNull()) { + if (d_createOutgoingBlobBuffer_result.isNull()) { UNEXPECTED_CALL(); } - return d_outgoingBlobBuffer.value(); + return d_createOutgoingBlobBuffer_result.value(); } void createIncomingBlobBuffer(bdlbb::BlobBuffer* blobBuffer) override { @@ -1663,31 +1663,34 @@ class DataPoolMock : public ntci::DataPool return dummyBlobBufferFactory; } - // auxilary functions + // auxiliary functions - void set_createIncomingBlobBuffer_WillAlwaysReturn( + void expect_createIncomingBlobBuffer_WillAlwaysReturn( const bsl::shared_ptr& blob) { - d_incomingBlobBuffer = blob; + d_createIncomingBlobBuffer_result = blob; } - void set_createOutgoingBlobBuffer_WillAlwaysReturn( + void expect_createOutgoingBlobBuffer_WillAlwaysReturn( const bsl::shared_ptr& blob) { - d_outgoingBlobBuffer = blob; + d_createOutgoingBlobBuffer_result = blob; } - void set_createOutgoingData_WillAlwaysReturn( - bsl::shared_ptr data) + void expect_createOutgoingData_WillAlwaysReturn( + const bsl::shared_ptr& data) { - d_outgoingData = data; + d_createOutgoingData_result = data; } private: - bsl::shared_ptr dummyBlobBufferFactory; - bdlb::NullableValue > d_incomingBlobBuffer; - bdlb::NullableValue > d_outgoingBlobBuffer; - bdlb::NullableValue > d_outgoingData; + bsl::shared_ptr dummyBlobBufferFactory; + bdlb::NullableValue > + d_createIncomingBlobBuffer_result; + bdlb::NullableValue > + d_createOutgoingBlobBuffer_result; + bdlb::NullableValue > + d_createOutgoingData_result; }; class ReactorMock : public ntci::Reactor @@ -1731,18 +1734,18 @@ class ReactorMock : public ntci::Reactor const bsl::shared_ptr& incomingBlobBufferFactory() const override { - if (d_incomingBlobBufferFactory.isNull()) { + if (d_incomingBlobBufferFactory_result.isNull()) { UNEXPECTED_CALL(); } - return d_incomingBlobBufferFactory.value(); + return d_incomingBlobBufferFactory_result.value(); } const bsl::shared_ptr& outgoingBlobBufferFactory() const override { - if (d_outgoingBlobBufferFactory.isNull()) { + if (d_outgoingBlobBufferFactory_result.isNull()) { UNEXPECTED_CALL(); } - return d_outgoingBlobBufferFactory.value(); + return d_outgoingBlobBufferFactory_result.value(); } ntci::Waiter registerWaiter( const ntca::WaiterOptions& waiterOptions) override @@ -1780,10 +1783,10 @@ class ReactorMock : public ntci::Reactor } void execute(const Functor& functor) override { - if (!d_executeExpected) { + if (!d_execute_expected) { UNEXPECTED_CALL(); } - d_executeExpected = false; + d_execute_expected = false; NTCCFG_TEST_FALSE(d_execute_functor.has_value()); d_execute_functor = functor; } @@ -1805,9 +1808,9 @@ class ReactorMock : public ntci::Reactor if (d_attachSocket_result.isNull()) { UNEXPECTED_CALL(); } - if (d_attachSocket_socket.has_value()) { - NTCCFG_TEST_EQ(socket, d_attachSocket_socket.value()); - d_attachSocket_socket.reset(); + if (d_attachSocket_arg1.has_value()) { + NTCCFG_TEST_EQ(socket, d_attachSocket_arg1.value()); + d_attachSocket_arg1.reset(); } const auto res = d_attachSocket_result.value(); d_attachSocket_result.reset(); @@ -1841,9 +1844,9 @@ class ReactorMock : public ntci::Reactor UNEXPECTED_CALL(); } - if (d_showWritable_socket.has_value()) { - NTCCFG_TEST_EQ(socket, d_showWritable_socket.value()); - d_showWritable_socket.reset(); + if (d_showWritable_arg1.has_value()) { + NTCCFG_TEST_EQ(socket, d_showWritable_arg1.value()); + d_showWritable_arg1.reset(); } const auto res = d_showWritable_result.value(); @@ -2015,10 +2018,10 @@ class ReactorMock : public ntci::Reactor } bool oneShot() const override { - if (d_oneShot.isNull()) { + if (d_oneShot_result.isNull()) { UNEXPECTED_CALL(); } - return d_oneShot.value(); + return d_oneShot_result.value(); } ntca::ReactorEventTrigger::Value trigger() const override { @@ -2047,10 +2050,10 @@ class ReactorMock : public ntci::Reactor } const bsl::shared_ptr& dataPool() const override { - if (d_dataPool.isNull()) { + if (d_dataPool_result.isNull()) { UNEXPECTED_CALL(); } - return d_dataPool.value(); + return d_dataPool_result.value(); } bool supportsOneShot(bool oneShot) const override { @@ -2076,10 +2079,10 @@ class ReactorMock : public ntci::Reactor } bool acquireHandleReservation() override { - if (d_aquireHandleReservation.isNull()) { + if (d_acquireHandleReservation_result.isNull()) { UNEXPECTED_CALL(); } - return d_aquireHandleReservation.value(); + return d_acquireHandleReservation_result.value(); } void releaseHandleReservation() override { @@ -2104,10 +2107,10 @@ class ReactorMock : public ntci::Reactor } size_t maxThreads() const override { - if (d_maxThreads.isNull()) { + if (d_maxThreads_result.isNull()) { UNEXPECTED_CALL(); } - return d_maxThreads.value(); + return d_maxThreads_result.value(); } bsl::shared_ptr createStrand( bslma::Allocator* basicAllocator) override @@ -2127,11 +2130,11 @@ class ReactorMock : public ntci::Reactor const bsl::shared_ptr& session, bslma::Allocator* basicAllocator) override { - if (d_timer.isNull()) { + if (d_timer_result.isNull()) { UNEXPECTED_CALL(); } - const auto timer = d_timer.value(); - d_timer->clear(); + const auto timer = d_timer_result.value(); + d_timer_result->clear(); return timer; } bsl::shared_ptr createTimer( @@ -2139,15 +2142,15 @@ class ReactorMock : public ntci::Reactor const ntci::TimerCallback& callback, bslma::Allocator* basicAllocator) override { - if (d_timer.isNull()) { + if (d_timer_result.isNull()) { UNEXPECTED_CALL(); } NTCCFG_TEST_TRUE(d_timerCallback.isNull()); d_timerCallback = callback; - const auto timer = d_timer.value(); - d_timer.reset(); + const auto timer = d_timer_result.value(); + d_timer_result.reset(); return timer; } const bsl::shared_ptr& strand() const override @@ -2161,81 +2164,81 @@ class ReactorMock : public ntci::Reactor return bsls::TimeInterval(); } - // auxilary methods - void set_dataPool_WillAlwaysReturn( + // auxiliary methods + void expect_dataPool_WillAlwaysReturn( const bsl::shared_ptr& dataPool) { - d_dataPool = dataPool; + d_dataPool_result = dataPool; } - void set_outgoingBlobBufferFactory_WillAlwaysReturn( - bsl::shared_ptr bufferFactory) + void expect_outgoingBlobBufferFactory_WillAlwaysReturn( + const bsl::shared_ptr& bufferFactory) { - d_outgoingBlobBufferFactory = bufferFactory; + d_outgoingBlobBufferFactory_result = bufferFactory; } - void set_incomingBlobBufferFactory_WillAlwaysReturn( - bsl::shared_ptr bufferFactory) + void expect_incomingBlobBufferFactory_WillAlwaysReturn( + const bsl::shared_ptr& bufferFactory) { - d_incomingBlobBufferFactory = bufferFactory; + d_incomingBlobBufferFactory_result = bufferFactory; } - void set_oneShot_WillAlwaysReturn(bool flag) + void expect_oneShot_WillAlwaysReturn(bool flag) { - d_oneShot = flag; + d_oneShot_result = flag; } - void set_maxThreads_WillAlwaysReturn(size_t val) + void expect_maxThreads_WillAlwaysReturn(size_t val) { - d_maxThreads = val; + d_maxThreads_result = val; } - void set_createTimer_WillOnceReturn( + void expect_createTimer_WillOnceReturn( const bsl::shared_ptr& timer) { - d_timer = timer; + d_timer_result = timer; } - void set_execute_expectedOnce() + void expect_execute_WillOnceReturn() { - d_executeExpected = true; + d_execute_expected = true; } - void set_aquireHandleReservation_WillAlwaysReturn(bool flag) + void expect_acquireHandleReservation_WillAlwaysReturn(bool flag) { - d_aquireHandleReservation = flag; + d_acquireHandleReservation_result = flag; } - void set_releaseHandleReservation_WillAlwaysReturn() + void expect_releaseHandleReservation_WillAlwaysReturn() { d_releaseHandleReservation = true; } - void set_attachSocket_WillOnceReturn( + void expect_attachSocket_WillOnceReturn( const bdlb::NullableValue >& socket, const ntsa::Error& result) { NTCCFG_TEST_TRUE(d_attachSocket_result.isNull()); - NTCCFG_TEST_TRUE(d_attachSocket_socket.isNull()); + NTCCFG_TEST_TRUE(d_attachSocket_arg1.isNull()); d_attachSocket_result = result; - d_attachSocket_socket = socket; + d_attachSocket_arg1 = socket; } - void set_showWritable_WillOnceReturn( + void expect_showWritable_WillOnceReturn( const bdlb::NullableValue >& socket, const ntsa::Error& error) { NTCCFG_TEST_TRUE(d_showWritable_result.isNull()); - NTCCFG_TEST_TRUE(d_showWritable_socket.isNull()); + NTCCFG_TEST_TRUE(d_showWritable_arg1.isNull()); d_showWritable_result = error; - d_showWritable_socket = socket; + d_showWritable_arg1 = socket; } - void set_detachSocket_WillOnceReturn( + void expect_detachSocket_WillOnceReturn( const bdlb::NullableValue >& socket, const bdlb::NullableValue& callback, @@ -2271,26 +2274,26 @@ class ReactorMock : public ntci::Reactor private: bdlb::NullableValue > - d_incomingBlobBufferFactory; + d_incomingBlobBufferFactory_result; bdlb::NullableValue > - d_outgoingBlobBufferFactory; + d_outgoingBlobBufferFactory_result; bsl::shared_ptr dummyStrand; - bdlb::NullableValue > d_dataPool; - bdlb::NullableValue d_oneShot; - bdlb::NullableValue d_maxThreads; - bdlb::NullableValue > d_timer; + bdlb::NullableValue > d_dataPool_result; + bdlb::NullableValue d_oneShot_result; + bdlb::NullableValue d_maxThreads_result; + bdlb::NullableValue > d_timer_result; bdlb::NullableValue d_timerCallback; - bool d_executeExpected; + bool d_execute_expected; bdlb::NullableValue d_execute_functor; - bdlb::NullableValue d_aquireHandleReservation; + bdlb::NullableValue d_acquireHandleReservation_result; bool d_releaseHandleReservation; bdlb::NullableValue > - d_attachSocket_socket; + d_attachSocket_arg1; bdlb::NullableValue d_attachSocket_result; bdlb::NullableValue > - d_showWritable_socket; + d_showWritable_arg1; bdlb::NullableValue d_showWritable_result; bdlb::NullableValue d_detachSocket_result; @@ -2305,19 +2308,19 @@ class TimerMock : public ntci::Timer ntsa::Error schedule(const bsls::TimeInterval& deadline, const bsls::TimeInterval& period) override { - if (d_scheduleReturn_error.isNull()) { + if (d_schedule_result.isNull()) { UNEXPECTED_CALL(); } - if (d_scheduleArg_deadline.has_value()) { - NTCCFG_TEST_EQ(deadline, d_scheduleArg_deadline.value()); - d_scheduleArg_deadline.reset(); + if (d_scheduleArg_arg1.has_value()) { + NTCCFG_TEST_EQ(deadline, d_scheduleArg_arg1.value()); + d_scheduleArg_arg1.reset(); } - if (d_scheduleArg_period.has_value()) { - NTCCFG_TEST_EQ(period, d_scheduleArg_period.value()); - d_scheduleArg_period.reset(); + if (d_scheduleArg_arg2.has_value()) { + NTCCFG_TEST_EQ(period, d_scheduleArg_arg2.value()); + d_scheduleArg_arg2.reset(); } - const auto error = d_scheduleReturn_error.value(); - d_scheduleReturn_error.reset(); + const auto error = d_schedule_result.value(); + d_schedule_result.reset(); return error; } @@ -2328,11 +2331,11 @@ class TimerMock : public ntci::Timer } ntsa::Error close() override { - if (d_close_error.isNull()) { + if (d_close_result.isNull()) { UNEXPECTED_CALL(); } - const auto res = d_close_error.value(); - d_close_error.reset(); + const auto res = d_close_result.value(); + d_close_result.reset(); return res; } void arrive(const bsl::shared_ptr& self, @@ -2377,28 +2380,28 @@ class TimerMock : public ntci::Timer return bsls::TimeInterval(); } - void set_schedule_willOnceReturn( + void expect_schedule_willOnceReturn( const bdlb::NullableValue& deadline, const bdlb::NullableValue& period, - ntsa::Error error) + const ntsa::Error& error) { - d_scheduleArg_deadline = deadline; - d_scheduleArg_period = period; - d_scheduleReturn_error = error; + d_scheduleArg_arg1 = deadline; + d_scheduleArg_arg2 = period; + d_schedule_result = error; } - void set_close_WillOnceReturn(const ntsa::Error& error) + void expect_close_WillOnceReturn(const ntsa::Error& error) { - d_close_error = error; + d_close_result = error; } private: bsl::shared_ptr dummyStrand; - bdlb::NullableValue d_scheduleArg_deadline; - bdlb::NullableValue d_scheduleArg_period; - bdlb::NullableValue d_scheduleReturn_error; - bdlb::NullableValue d_close_error; + bdlb::NullableValue d_scheduleArg_arg1; + bdlb::NullableValue d_scheduleArg_arg2; + bdlb::NullableValue d_schedule_result; + bdlb::NullableValue d_close_result; }; } // close namespace mock @@ -4409,21 +4412,23 @@ NTCCFG_TEST_CASE(22) bsl::shared_ptr dataPoolMock; dataPoolMock.createInplace(&ta); - reactorMock->set_dataPool_WillAlwaysReturn(dataPoolMock); + reactorMock->expect_dataPool_WillAlwaysReturn(dataPoolMock); bsl::shared_ptr bufferFactoryMock; bufferFactoryMock.createInplace(&ta); - reactorMock->set_outgoingBlobBufferFactory_WillAlwaysReturn( + reactorMock->expect_outgoingBlobBufferFactory_WillAlwaysReturn( bufferFactoryMock); - reactorMock->set_incomingBlobBufferFactory_WillAlwaysReturn( + reactorMock->expect_incomingBlobBufferFactory_WillAlwaysReturn( bufferFactoryMock); - reactorMock->set_oneShot_WillAlwaysReturn(false); - reactorMock->set_maxThreads_WillAlwaysReturn(1); + reactorMock->expect_oneShot_WillAlwaysReturn(false); + reactorMock->expect_maxThreads_WillAlwaysReturn(1); - dataPoolMock->set_createIncomingBlobBuffer_WillAlwaysReturn(nullBlob); - dataPoolMock->set_createOutgoingBlobBuffer_WillAlwaysReturn(nullBlob); - dataPoolMock->set_createOutgoingData_WillAlwaysReturn(dummyData); + dataPoolMock->expect_createIncomingBlobBuffer_WillAlwaysReturn( + nullBlob); + dataPoolMock->expect_createOutgoingBlobBuffer_WillAlwaysReturn( + nullBlob); + dataPoolMock->expect_createOutgoingData_WillAlwaysReturn(dummyData); const ntca::StreamSocketOptions options; @@ -4438,9 +4443,9 @@ NTCCFG_TEST_CASE(22) bsl::shared_ptr connectRetryTimerMock; connectRetryTimerMock.createInplace(&ta); - reactorMock->set_createTimer_WillOnceReturn(connectRetryTimerMock); + reactorMock->expect_createTimer_WillOnceReturn(connectRetryTimerMock); - connectRetryTimerMock->set_schedule_willOnceReturn( + connectRetryTimerMock->expect_schedule_willOnceReturn( bdlb::NullOptType::makeInitialValue(), bdlb::NullOptType::makeInitialValue(), ntsa::Error()); @@ -4460,7 +4465,7 @@ NTCCFG_TEST_CASE(22) NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); - resolverMock->set_getEndpoint_WillOnceReturn( + resolverMock->expect_getEndpoint_WillOnceReturn( epName, bdlb::NullOptType::makeInitialValue(), ntsa::Error()); @@ -4473,8 +4478,8 @@ NTCCFG_TEST_CASE(22) NTCI_LOG_DEBUG("Shutdown socket while it is waiting for remote " "endpoint resolution"); - connectRetryTimerMock->set_close_WillOnceReturn(ntsa::Error()); - reactorMock->set_execute_expectedOnce(); + connectRetryTimerMock->expect_close_WillOnceReturn(ntsa::Error()); + reactorMock->expect_execute_WillOnceReturn(); socket.shutdown(ntsa::ShutdownType::e_BOTH, ntsa::ShutdownMode::e_GRACEFUL); @@ -4517,21 +4522,23 @@ NTCCFG_TEST_CASE(23) bsl::shared_ptr dataPoolMock; dataPoolMock.createInplace(&ta); - reactorMock->set_dataPool_WillAlwaysReturn(dataPoolMock); + reactorMock->expect_dataPool_WillAlwaysReturn(dataPoolMock); bsl::shared_ptr bufferFactoryMock; bufferFactoryMock.createInplace(&ta); - reactorMock->set_outgoingBlobBufferFactory_WillAlwaysReturn( + reactorMock->expect_outgoingBlobBufferFactory_WillAlwaysReturn( bufferFactoryMock); - reactorMock->set_incomingBlobBufferFactory_WillAlwaysReturn( + reactorMock->expect_incomingBlobBufferFactory_WillAlwaysReturn( bufferFactoryMock); - reactorMock->set_oneShot_WillAlwaysReturn(false); - reactorMock->set_maxThreads_WillAlwaysReturn(1); + reactorMock->expect_oneShot_WillAlwaysReturn(false); + reactorMock->expect_maxThreads_WillAlwaysReturn(1); - dataPoolMock->set_createIncomingBlobBuffer_WillAlwaysReturn(nullBlob); - dataPoolMock->set_createOutgoingBlobBuffer_WillAlwaysReturn(nullBlob); - dataPoolMock->set_createOutgoingData_WillAlwaysReturn(dummyData); + dataPoolMock->expect_createIncomingBlobBuffer_WillAlwaysReturn( + nullBlob); + dataPoolMock->expect_createOutgoingBlobBuffer_WillAlwaysReturn( + nullBlob); + dataPoolMock->expect_createOutgoingData_WillAlwaysReturn(dummyData); const ntca::StreamSocketOptions options; @@ -4548,9 +4555,9 @@ NTCCFG_TEST_CASE(23) bsl::shared_ptr connectRetryTimerMock; connectRetryTimerMock.createInplace(&ta); - reactorMock->set_createTimer_WillOnceReturn(connectRetryTimerMock); + reactorMock->expect_createTimer_WillOnceReturn(connectRetryTimerMock); - connectRetryTimerMock->set_schedule_willOnceReturn( + connectRetryTimerMock->expect_schedule_willOnceReturn( bdlb::NullOptType::makeInitialValue(), bdlb::NullOptType::makeInitialValue(), ntsa::Error()); @@ -4570,10 +4577,10 @@ NTCCFG_TEST_CASE(23) NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); - reactorMock->set_aquireHandleReservation_WillAlwaysReturn(true); - reactorMock->set_releaseHandleReservation_WillAlwaysReturn(); - reactorMock->set_attachSocket_WillOnceReturn(socket, ntsa::Error()); - reactorMock->set_showWritable_WillOnceReturn(socket, ntsa::Error()); + reactorMock->expect_acquireHandleReservation_WillAlwaysReturn(true); + reactorMock->expect_releaseHandleReservation_WillAlwaysReturn(); + reactorMock->expect_attachSocket_WillOnceReturn(socket, ntsa::Error()); + reactorMock->expect_showWritable_WillOnceReturn(socket, ntsa::Error()); const auto timerCallback = reactorMock->extract_timerCallback(); ntca::TimerEvent timerEvent; @@ -4583,9 +4590,9 @@ NTCCFG_TEST_CASE(23) NTCI_LOG_DEBUG( "Shutdown socket while it is waiting for connection result"); - connectRetryTimerMock->set_close_WillOnceReturn(ntsa::Error()); + connectRetryTimerMock->expect_close_WillOnceReturn(ntsa::Error()); - reactorMock->set_detachSocket_WillOnceReturn( + reactorMock->expect_detachSocket_WillOnceReturn( socket, bdlb::NullOptType::makeInitialValue(), ntsa::Error()); @@ -4596,7 +4603,7 @@ NTCCFG_TEST_CASE(23) const auto detachCallback = reactorMock->extract_detachCallback(); NTCCFG_TEST_TRUE(detachCallback); - reactorMock->set_execute_expectedOnce(); + reactorMock->expect_execute_WillOnceReturn(); detachCallback(nullStrand); const auto callback = reactorMock->extract_execute_functor(); From adcd76a1c36850e6a840a6ee73845d52e660d085 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Wed, 20 Mar 2024 21:10:29 +0200 Subject: [PATCH 04/60] introduce one more TC + huge refactoring of createTimer and schedule methods --- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 559 +++++++++++++++++++++--- 1 file changed, 489 insertions(+), 70 deletions(-) diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index 56342843..dd9da557 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -2130,28 +2130,18 @@ class ReactorMock : public ntci::Reactor const bsl::shared_ptr& session, bslma::Allocator* basicAllocator) override { - if (d_timer_result.isNull()) { - UNEXPECTED_CALL(); - } - const auto timer = d_timer_result.value(); - d_timer_result->clear(); - return timer; + UNEXPECTED_CALL(); + + return bsl::shared_ptr(); } bsl::shared_ptr createTimer( const ntca::TimerOptions& options, const ntci::TimerCallback& callback, bslma::Allocator* basicAllocator) override { - if (d_timer_result.isNull()) { - UNEXPECTED_CALL(); - } - - NTCCFG_TEST_TRUE(d_timerCallback.isNull()); - d_timerCallback = callback; - - const auto timer = d_timer_result.value(); - d_timer_result.reset(); - return timer; + return d_invocation_createTimer.invoke(options, + callback, + basicAllocator); } const bsl::shared_ptr& strand() const override { @@ -2164,6 +2154,156 @@ class ReactorMock : public ntci::Reactor return bsls::TimeInterval(); } + public: + // Helper data structures + + struct Invocation_createTimer { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_arg2; + bdlb::NullableValue d_arg3; + bdlb::NullableValue > d_result; + ntca::TimerOptions* d_arg1_out; + ntci::TimerCallback* d_arg2_out; + bslma::Allocator** d_arg3_out; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_arg2() + , d_arg3() + , d_result() + , d_arg1_out(0) + , d_arg2_out(0) + , d_arg3_out(0) + { + } + }; + + public: + Invocation_createTimer& expect( + const bdlb::NullableValue& arg1, + const bdlb::NullableValue& arg2, + const bdlb::NullableValue& arg3) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1 = arg1; + invocation.d_arg2 = arg2; + invocation.d_arg3 = arg3; + return *this; + } + Invocation_createTimer& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_createTimer& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_createTimer& willReturn( + const bsl::shared_ptr& result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_createTimer& saveArg1(ntca::TimerOptions& arg) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_arg1_out, 0); + invocation.d_arg1_out = &arg; + return *this; + } + Invocation_createTimer& saveArg2(ntci::TimerCallback& arg) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_arg2_out, 0); + invocation.d_arg2_out = &arg; + return *this; + } + Invocation_createTimer& saveArg3(bslma::Allocator*& arg) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_arg3_out, 0); + invocation.d_arg3_out = &arg; + return *this; + } + + bsl::shared_ptr invoke(const ntca::TimerOptions& arg1, + const ntci::TimerCallback& arg2, + bslma::Allocator* arg3) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg2.has_value()) { + NTCCFG_TEST_EQ(arg2, invocation.d_arg2.value()); + } + + if (invocation.d_arg3.has_value()) { + NTCCFG_TEST_EQ(arg3, invocation.d_arg3.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + if (invocation.d_arg2_out) { + *invocation.d_arg2_out = arg2; + } + + if (invocation.d_arg3_out) { + *invocation.d_arg3_out = arg3; + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + public: // auxiliary methods void expect_dataPool_WillAlwaysReturn( const bsl::shared_ptr& dataPool) @@ -2193,10 +2333,18 @@ class ReactorMock : public ntci::Reactor d_maxThreads_result = val; } - void expect_createTimer_WillOnceReturn( - const bsl::shared_ptr& timer) + // void expect_createTimer_WillOnceReturn( + // const bsl::shared_ptr& timer) + // { + // d_timer_result = timer; + // } + + Invocation_createTimer& expect_createTimer( + const bdlb::NullableValue& arg1, + const bdlb::NullableValue& arg2, + const bdlb::NullableValue& arg3) { - d_timer_result = timer; + return d_invocation_createTimer.expect(arg1, arg2, arg3); } void expect_execute_WillOnceReturn() @@ -2249,13 +2397,13 @@ class ReactorMock : public ntci::Reactor d_detachSocket_arg2 = callback; } - ntci::TimerCallback extract_timerCallback() - { - NTCCFG_TEST_TRUE(d_timerCallback.has_value()); - const auto res = d_timerCallback.value(); - d_timerCallback.reset(); - return res; - } + // ntci::TimerCallback extract_timerCallback() + // { + // NTCCFG_TEST_TRUE(d_timerCallback.has_value()); + // const auto res = d_timerCallback.value(); + // d_timerCallback.reset(); + // return res; + // } ntci::Reactor::Functor extract_execute_functor() { @@ -2281,10 +2429,10 @@ class ReactorMock : public ntci::Reactor bdlb::NullableValue > d_dataPool_result; bdlb::NullableValue d_oneShot_result; bdlb::NullableValue d_maxThreads_result; - bdlb::NullableValue > d_timer_result; - bdlb::NullableValue d_timerCallback; - bool d_execute_expected; - bdlb::NullableValue d_execute_functor; + // bdlb::NullableValue > d_timer_result; + // bdlb::NullableValue d_timerCallback; + bool d_execute_expected; + bdlb::NullableValue d_execute_functor; bdlb::NullableValue d_acquireHandleReservation_result; bool d_releaseHandleReservation; @@ -2300,6 +2448,8 @@ class ReactorMock : public ntci::Reactor bdlb::NullableValue > d_detachSocket_arg1; bdlb::NullableValue d_detachSocket_arg2; + + Invocation_createTimer d_invocation_createTimer; }; class TimerMock : public ntci::Timer @@ -2308,21 +2458,7 @@ class TimerMock : public ntci::Timer ntsa::Error schedule(const bsls::TimeInterval& deadline, const bsls::TimeInterval& period) override { - if (d_schedule_result.isNull()) { - UNEXPECTED_CALL(); - } - if (d_scheduleArg_arg1.has_value()) { - NTCCFG_TEST_EQ(deadline, d_scheduleArg_arg1.value()); - d_scheduleArg_arg1.reset(); - } - if (d_scheduleArg_arg2.has_value()) { - NTCCFG_TEST_EQ(period, d_scheduleArg_arg2.value()); - d_scheduleArg_arg2.reset(); - } - const auto error = d_schedule_result.value(); - d_schedule_result.reset(); - - return error; + return d_schedule_invocation.invoke(deadline, period); } ntsa::Error cancel() override { @@ -2380,14 +2516,135 @@ class TimerMock : public ntci::Timer return bsls::TimeInterval(); } - void expect_schedule_willOnceReturn( - const bdlb::NullableValue& deadline, - const bdlb::NullableValue& period, - const ntsa::Error& error) + struct Invocation_schedule { + // const bsls::TimeInterval& deadline, + // const bsls::TimeInterval& period + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_arg2; + bdlb::NullableValue d_result; + bsls::TimeInterval* d_arg1_out; + bsls::TimeInterval* d_arg2_out; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_arg2() + , d_result() + , d_arg1_out(0) + , d_arg2_out(0) + { + } + }; + + public: + Invocation_schedule& expect( + const bdlb::NullableValue& arg1, + const bdlb::NullableValue& arg2) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1 = arg1; + invocation.d_arg2 = arg2; + return *this; + } + Invocation_schedule& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_schedule& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_schedule& willReturn(const ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_schedule& saveArg1(bsls::TimeInterval& arg) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_arg1_out, 0); + invocation.d_arg1_out = &arg; + return *this; + } + Invocation_schedule& saveArg2(bsls::TimeInterval& arg) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_arg2_out, 0); + invocation.d_arg2_out = &arg; + return *this; + } + + ntsa::Error invoke(const bsls::TimeInterval& arg1, + const bsls::TimeInterval& arg2) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg2.has_value()) { + NTCCFG_TEST_EQ(arg2, invocation.d_arg2.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + if (invocation.d_arg2_out) { + *invocation.d_arg2_out = arg2; + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_schedule& expect_schedule( + const bdlb::NullableValue& arg1, + const bdlb::NullableValue& arg2) { - d_scheduleArg_arg1 = deadline; - d_scheduleArg_arg2 = period; - d_schedule_result = error; + return d_schedule_invocation.expect(arg1, arg2); } void expect_close_WillOnceReturn(const ntsa::Error& error) @@ -2398,10 +2655,9 @@ class TimerMock : public ntci::Timer private: bsl::shared_ptr dummyStrand; - bdlb::NullableValue d_scheduleArg_arg1; - bdlb::NullableValue d_scheduleArg_arg2; - bdlb::NullableValue d_schedule_result; - bdlb::NullableValue d_close_result; + bdlb::NullableValue d_close_result; + + Invocation_schedule d_schedule_invocation; }; } // close namespace mock @@ -4391,6 +4647,8 @@ NTCCFG_TEST_CASE(22) { NTCI_LOG_DEBUG("Fixture setup, socket creation..."); + const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + bdlb::NullableValue connectResult; bsl::shared_ptr nullPool; @@ -4443,12 +4701,16 @@ NTCCFG_TEST_CASE(22) bsl::shared_ptr connectRetryTimerMock; connectRetryTimerMock.createInplace(&ta); - reactorMock->expect_createTimer_WillOnceReturn(connectRetryTimerMock); - connectRetryTimerMock->expect_schedule_willOnceReturn( - bdlb::NullOptType::makeInitialValue(), - bdlb::NullOptType::makeInitialValue(), - ntsa::Error()); + ntci::TimerCallback retryTimerCallback; + reactorMock->expect_createTimer(doNotCare, doNotCare, doNotCare) + .willOnce() + .willReturn(connectRetryTimerMock) + .saveArg2(retryTimerCallback); + + connectRetryTimerMock->expect_schedule(doNotCare, doNotCare) + .willOnce() + .willReturn(ntsa::Error()); const ntci::ConnectFunction connectCallback = [&connectResult](const bsl::shared_ptr& connector, @@ -4470,10 +4732,9 @@ NTCCFG_TEST_CASE(22) bdlb::NullOptType::makeInitialValue(), ntsa::Error()); - const auto timerCallback = reactorMock->extract_timerCallback(); ntca::TimerEvent timerEvent; timerEvent.setType(ntca::TimerEventType::e_DEADLINE); - timerCallback(connectRetryTimerMock, timerEvent, nullStrand); + retryTimerCallback(connectRetryTimerMock, timerEvent, nullStrand); NTCI_LOG_DEBUG("Shutdown socket while it is waiting for remote " "endpoint resolution"); @@ -4501,6 +4762,8 @@ NTCCFG_TEST_CASE(23) { NTCI_LOG_DEBUG("Fixture setup, socket creation..."); + const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + bdlb::NullableValue connectResult; bsl::shared_ptr nullPool; @@ -4555,12 +4818,16 @@ NTCCFG_TEST_CASE(23) bsl::shared_ptr connectRetryTimerMock; connectRetryTimerMock.createInplace(&ta); - reactorMock->expect_createTimer_WillOnceReturn(connectRetryTimerMock); - connectRetryTimerMock->expect_schedule_willOnceReturn( - bdlb::NullOptType::makeInitialValue(), - bdlb::NullOptType::makeInitialValue(), - ntsa::Error()); + ntci::TimerCallback retryTimerCallback; + reactorMock->expect_createTimer(doNotCare, doNotCare, doNotCare) + .willOnce() + .willReturn(connectRetryTimerMock) + .saveArg2(retryTimerCallback); + + connectRetryTimerMock->expect_schedule(doNotCare, doNotCare) + .willOnce() + .willReturn(ntsa::Error()); const ntci::ConnectFunction connectCallback = [&connectResult](const bsl::shared_ptr& connector, @@ -4582,10 +4849,9 @@ NTCCFG_TEST_CASE(23) reactorMock->expect_attachSocket_WillOnceReturn(socket, ntsa::Error()); reactorMock->expect_showWritable_WillOnceReturn(socket, ntsa::Error()); - const auto timerCallback = reactorMock->extract_timerCallback(); ntca::TimerEvent timerEvent; timerEvent.setType(ntca::TimerEventType::e_DEADLINE); - timerCallback(connectRetryTimerMock, timerEvent, nullStrand); + retryTimerCallback(connectRetryTimerMock, timerEvent, nullStrand); NTCI_LOG_DEBUG( "Shutdown socket while it is waiting for connection result"); @@ -4616,6 +4882,158 @@ NTCCFG_TEST_CASE(23) NTCCFG_TEST_ASSERT(ta.numBlocksInUse() == 0); } +NTCCFG_TEST_CASE(24) +{ + NTCI_LOG_CONTEXT(); + + ntccfg::TestAllocator ta; + { + NTCI_LOG_DEBUG("Fixture setup, socket creation..."); + + const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + + bdlb::NullableValue connectResult; + + bsl::shared_ptr nullPool; + bsl::shared_ptr nullMetrics; + bsl::shared_ptr nullBlob; + bsl::shared_ptr nullStrand; + + bsl::shared_ptr dummyData; + dummyData.createInplace(&ta); + + bsl::shared_ptr resolverMock; + resolverMock.createInplace(&ta); + + bsl::shared_ptr reactorMock; + reactorMock.createInplace(&ta); + + bsl::shared_ptr socketMock; + socketMock.createInplace(&ta); + + bsl::shared_ptr dataPoolMock; + dataPoolMock.createInplace(&ta); + reactorMock->expect_dataPool_WillAlwaysReturn(dataPoolMock); + + bsl::shared_ptr bufferFactoryMock; + bufferFactoryMock.createInplace(&ta); + reactorMock->expect_outgoingBlobBufferFactory_WillAlwaysReturn( + bufferFactoryMock); + reactorMock->expect_incomingBlobBufferFactory_WillAlwaysReturn( + bufferFactoryMock); + + reactorMock->expect_oneShot_WillAlwaysReturn(false); + reactorMock->expect_maxThreads_WillAlwaysReturn(1); + + dataPoolMock->expect_createIncomingBlobBuffer_WillAlwaysReturn( + nullBlob); + dataPoolMock->expect_createOutgoingBlobBuffer_WillAlwaysReturn( + nullBlob); + dataPoolMock->expect_createOutgoingData_WillAlwaysReturn(dummyData); + + const ntca::StreamSocketOptions options; + + bsl::shared_ptr socket; + socket.createInplace(&ta, + options, + resolverMock, + reactorMock, + nullPool, + nullMetrics, + &ta); + + NTCI_LOG_DEBUG("Connection initiation..."); + + bsl::shared_ptr connectDeadlineTimerMock; + bsls::TimeInterval deadlineTime; + ntci::TimerCallback deadlineTimerCallback; + { + deadlineTime.setTotalHours(1); + + connectDeadlineTimerMock.createInplace(&ta); + reactorMock->expect_createTimer(doNotCare, doNotCare, doNotCare) + .willOnce() + .willReturn(connectDeadlineTimerMock) + .saveArg2(deadlineTimerCallback); + + connectDeadlineTimerMock + ->expect_schedule(deadlineTime, bsls::TimeInterval()) + .willOnce() + .willReturn(ntsa::Error()); + } + + bsl::shared_ptr connectRetryTimerMock; + ntci::TimerCallback retryTimerCallback; + { + connectRetryTimerMock.createInplace(&ta); + + reactorMock->expect_createTimer(doNotCare, doNotCare, doNotCare) + .willOnce() + .willReturn(connectRetryTimerMock) + .saveArg2(retryTimerCallback); + + connectRetryTimerMock->expect_schedule(doNotCare, doNotCare) + .willOnce() + .willReturn(ntsa::Error()); + } + + const ntci::ConnectFunction connectCallback = + [&connectResult](const bsl::shared_ptr& connector, + const ntca::ConnectEvent& event) { + NTCCFG_TEST_FALSE(connectResult.has_value()); + connectResult = event; + }; + + ntca::ConnectOptions connectOptions; + connectOptions.setDeadline(deadlineTime); + + const ntsa::Endpoint ep{"127.0.0.1:1234"}; + + socket->connect(ep, connectOptions, connectCallback); + + NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); + + reactorMock->expect_acquireHandleReservation_WillAlwaysReturn(true); + reactorMock->expect_releaseHandleReservation_WillAlwaysReturn(); + reactorMock->expect_attachSocket_WillOnceReturn(socket, ntsa::Error()); + reactorMock->expect_showWritable_WillOnceReturn(socket, ntsa::Error()); + + ntca::TimerEvent timerEvent; + timerEvent.setType(ntca::TimerEventType::e_DEADLINE); + retryTimerCallback(connectRetryTimerMock, timerEvent, nullStrand); + + NTCI_LOG_DEBUG( + "Shutdown socket while it is waiting for connection result"); + + { + connectRetryTimerMock->expect_close_WillOnceReturn(ntsa::Error()); + connectDeadlineTimerMock->expect_close_WillOnceReturn( + ntsa::Error()); + + reactorMock->expect_detachSocket_WillOnceReturn(socket, + doNotCare, + ntsa::Error()); + } + + socket->shutdown(ntsa::ShutdownType::e_BOTH, + ntsa::ShutdownMode::e_GRACEFUL); + + const auto detachCallback = reactorMock->extract_detachCallback(); + NTCCFG_TEST_TRUE(detachCallback); + + reactorMock->expect_execute_WillOnceReturn(); + detachCallback(nullStrand); + + const auto callback = reactorMock->extract_execute_functor(); + callback(); + + NTCCFG_TEST_TRUE(connectResult.has_value()); + NTCCFG_TEST_EQ(connectResult.value().type(), + ntca::ConnectEventType::e_ERROR); + } + NTCCFG_TEST_ASSERT(ta.numBlocksInUse() == 0); +} + NTCCFG_TEST_DRIVER { NTCCFG_TEST_REGISTER(1); @@ -4648,5 +5066,6 @@ NTCCFG_TEST_DRIVER NTCCFG_TEST_REGISTER(22); NTCCFG_TEST_REGISTER(23); + NTCCFG_TEST_REGISTER(24); } NTCCFG_TEST_DRIVER_END; From 50e006f628556c9132f63b920301f4939864f4d1 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Thu, 21 Mar 2024 19:09:42 +0200 Subject: [PATCH 05/60] Inject mocked ntsi::StreamSocket into tested ntcr::StreamSocket and update TC22 --- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 1086 ++++++++++++++++++++++- 1 file changed, 1068 insertions(+), 18 deletions(-) diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index dd9da557..7dd65e86 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1592,25 +1592,1025 @@ class StreamSocketMock : public ntsi::StreamSocket { public: ntsa::Handle handle() const override + { + return d_invocation_handle.invoke(); + } + ntsa::Error open(ntsa::Transport::Value transport) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error acquire(ntsa::Handle handle) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Handle release() override { UNEXPECTED_CALL(); return 0; } - ntsa::Error open(ntsa::Transport::Value transport) override + ntsa::Error bind(const ntsa::Endpoint& endpoint, + bool reuseAddress) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error bindAny(ntsa::Transport::Value transport, + bool reuseAddress) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error connect(const ntsa::Endpoint& endpoint) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error send(ntsa::SendContext* context, + const bdlbb::Blob& data, + const ntsa::SendOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error send(ntsa::SendContext* context, + const ntsa::Data& data, + const ntsa::SendOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error receive(ntsa::ReceiveContext* context, + bdlbb::Blob* data, + const ntsa::ReceiveOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error receive(ntsa::ReceiveContext* context, + ntsa::Data* data, + const ntsa::ReceiveOptions& options) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error receiveNotifications( + ntsa::NotificationQueue* notifications) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error shutdown(ntsa::ShutdownType::Value direction) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error unlink() override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + ntsa::Error close() override + { + return d_invocation_close.invoke(); + } + ntsa::Error sourceEndpoint(ntsa::Endpoint* result) const override + { + return d_invocation_sourceEndpoint.invoke(result); + } + ntsa::Error remoteEndpoint(ntsa::Endpoint* result) const override + { + return d_invocation_remoteEndpoint.invoke(result); + } + ntsa::Error setBlocking(bool blocking) override + { + return d_invocation_setBlocking.invoke(blocking); + } + ntsa::Error setOption(const ntsa::SocketOption& option) override + { + return d_invocation_setOption.invoke(option); + } + ntsa::Error getOption(ntsa::SocketOption* option, + ntsa::SocketOptionType::Value type) override + { + return d_invocation_getOption.invoke(option, type); + } + ntsa::Error getLastError(ntsa::Error* result) override + { + UNEXPECTED_CALL(); + return ntsa::Error(); + } + size_t maxBuffersPerSend() const override + { + return d_invocation_maxBuffersPerSend.invoke(); + } + size_t maxBuffersPerReceive() const override + { + return d_invocation_maxBuffersPerReceive.invoke(); + } + + struct Invocation_handle { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_result; + + InvocationData() + : d_expectedCalls(0) + , d_result() + { + } + }; + + public: + Invocation_handle& expect() + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + return *this; + } + Invocation_handle& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_handle& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_handle& willReturn(ntsa::Handle result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + ntsa::Handle invoke() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_handle& expect_handle() + { + return d_invocation_handle.expect(); + } + + struct Invocation_close { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_result; + + InvocationData() + : d_expectedCalls(0) + , d_result() + { + } + }; + + public: + Invocation_close& expect() + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + return *this; + } + Invocation_close& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_close& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_close& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + ntsa::Error invoke() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_close& expect_close() + { + return d_invocation_close.expect(); + } + + struct Invocation_maxBuffersPerSend { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_result; + + InvocationData() + : d_expectedCalls(0) + , d_result() + { + } + }; + + public: + Invocation_maxBuffersPerSend& expect() + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + return *this; + } + Invocation_maxBuffersPerSend& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_maxBuffersPerSend& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_maxBuffersPerSend& willReturn(bsl::size_t result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + bsl::size_t invoke() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_maxBuffersPerSend& expect_maxBuffersPerSend() + { + return d_invocation_maxBuffersPerSend.expect(); + } + + struct Invocation_maxBuffersPerReceive { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_result; + + InvocationData() + : d_expectedCalls(0) + , d_result() + { + } + }; + + public: + Invocation_maxBuffersPerReceive& expect() + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + return *this; + } + Invocation_maxBuffersPerReceive& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_maxBuffersPerReceive& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_maxBuffersPerReceive& willReturn(bsl::size_t result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + bsl::size_t invoke() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_maxBuffersPerReceive& expect_maxBuffersPerReceive() + { + return d_invocation_maxBuffersPerReceive.expect(); + } + + struct Invocation_setBlocking { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_result; + bool* d_arg1_out; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_result() + , d_arg1_out(0) + { + } + }; + + public: + Invocation_setBlocking& expect(const bdlb::NullableValue& arg1) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + + invocation.d_arg1 = arg1; + + return *this; + } + Invocation_setBlocking& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_setBlocking& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_setBlocking& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_setBlocking& saveArg1(bool& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_out = &arg1; + return *this; + } + + ntsa::Error invoke(bool arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_setBlocking& expect_setBlocking( + const bdlb::NullableValue& arg1) + { + return d_invocation_setBlocking.expect(arg1); + } + + struct Invocation_setOption { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_result; + ntsa::SocketOption* d_arg1_out; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_result() + , d_arg1_out(0) + { + } + }; + + public: + Invocation_setOption& expect( + const bdlb::NullableValue& arg1) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + + invocation.d_arg1 = arg1; + + return *this; + } + Invocation_setOption& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_setOption& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_setOption& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_setOption& saveArg1(ntsa::SocketOption& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_out = &arg1; + return *this; + } + + ntsa::Error invoke(const ntsa::SocketOption& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_setOption& expect_setOption( + const bdlb::NullableValue& arg1) + { + return d_invocation_setOption.expect(arg1); + } + + struct Invocation_sourceEndpoint { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_result; + ntsa::Endpoint** d_arg1_out; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_result() + , d_arg1_out(0) + { + } + }; + + public: + Invocation_sourceEndpoint& expect( + const bdlb::NullableValue& arg1) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + + invocation.d_arg1 = arg1; + + return *this; + } + Invocation_sourceEndpoint& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_sourceEndpoint& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_sourceEndpoint& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_sourceEndpoint& saveArg1(ntsa::Endpoint*& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_out = &arg1; + return *this; + } + + ntsa::Error invoke(ntsa::Endpoint* arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_sourceEndpoint& expect_sourceEndpoint( + const bdlb::NullableValue& arg1) { - UNEXPECTED_CALL(); - return ntsa::Error(); + return d_invocation_sourceEndpoint.expect(arg1); } - ntsa::Error acquire(ntsa::Handle handle) override + + struct Invocation_remoteEndpoint { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_result; + ntsa::Endpoint** d_arg1_out; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_result() + , d_arg1_out(0) + { + } + }; + + public: + Invocation_remoteEndpoint& expect( + const bdlb::NullableValue& arg1) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + + invocation.d_arg1 = arg1; + + return *this; + } + Invocation_remoteEndpoint& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_remoteEndpoint& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_remoteEndpoint& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_remoteEndpoint& saveArg1(ntsa::Endpoint*& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_out = &arg1; + return *this; + } + + ntsa::Error invoke(ntsa::Endpoint* arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_remoteEndpoint& expect_remoteEndpoint( + const bdlb::NullableValue& arg1) { - UNEXPECTED_CALL(); - return ntsa::Error(); + return d_invocation_remoteEndpoint.expect(arg1); } - ntsa::Handle release() override + + struct Invocation_getOption { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_arg2; + bdlb::NullableValue d_result; + ntsa::SocketOption** d_arg1_out; + ntsa::SocketOptionType::Value* d_arg2_out; + bdlb::NullableValue d_arg1_set; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_arg2() + , d_result() + , d_arg1_out(0) + , d_arg2_out(0) + , d_arg1_set() + { + } + }; + + public: + Invocation_getOption& expect( + const bdlb::NullableValue& arg1, + const bdlb::NullableValue& arg2) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + + invocation.d_arg1 = arg1; + invocation.d_arg2 = arg2; + + return *this; + } + Invocation_getOption& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_getOption& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_getOption& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_getOption& saveArg1(ntsa::SocketOption*& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_out = &arg1; + return *this; + } + + Invocation_getOption& setArg1(const ntsa::SocketOption& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_set = arg1; + return *this; + } + + Invocation_getOption& saveArg2(ntsa::SocketOptionType::Value& arg2) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg2_out = &arg2; + return *this; + } + + ntsa::Error invoke(ntsa::SocketOption* arg1, + ntsa::SocketOptionType::Value arg2) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg2.has_value()) { + NTCCFG_TEST_EQ(arg2, invocation.d_arg2.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + if (invocation.d_arg2_out) { + *invocation.d_arg2_out = arg2; + } + + if (invocation.d_arg1_set.has_value()) { + *arg1 = invocation.d_arg1_set.value(); + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_getOption& expect_getOption( + const bdlb::NullableValue& arg1, + const bdlb::NullableValue& arg2) { - UNEXPECTED_CALL(); - return 0; + return d_invocation_getOption.expect(arg1, arg2); } + + private: + mutable Invocation_handle d_invocation_handle; + mutable Invocation_close d_invocation_close; + mutable Invocation_maxBuffersPerSend d_invocation_maxBuffersPerSend; + mutable Invocation_maxBuffersPerReceive d_invocation_maxBuffersPerReceive; + mutable Invocation_setBlocking d_invocation_setBlocking; + mutable Invocation_setOption d_invocation_setOption; + mutable Invocation_getOption d_invocation_getOption; + mutable Invocation_sourceEndpoint d_invocation_sourceEndpoint; + mutable Invocation_remoteEndpoint d_invocation_remoteEndpoint; }; class DataPoolMock : public ntci::DataPool @@ -4647,7 +5647,8 @@ NTCCFG_TEST_CASE(22) { NTCI_LOG_DEBUG("Fixture setup, socket creation..."); - const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + const ntsa::Handle handle = 22; bdlb::NullableValue connectResult; @@ -4690,12 +5691,53 @@ NTCCFG_TEST_CASE(22) const ntca::StreamSocketOptions options; - ntcr::StreamSocket socket(options, - resolverMock, - reactorMock, - nullPool, - nullMetrics, - &ta); + bsl::shared_ptr socket; + socket.createInplace(&ta, + options, + resolverMock, + reactorMock, + nullPool, + nullMetrics, + &ta); + + socketMock->expect_handle().willAlways().willReturn(handle); + socketMock->expect_setBlocking(false).willOnce().willReturn( + ntsa::Error()); + socketMock->expect_setBlocking(false).willOnce().willReturn( + ntsa::Error()); //TODO: for some reason it is called twice + socketMock->expect_setOption(doNotCare).willAlways().willReturn( + ntsa::Error()); + socketMock->expect_sourceEndpoint(doNotCare).willOnce().willReturn( + ntsa::Error::invalid()); + socketMock->expect_remoteEndpoint(doNotCare).willOnce().willReturn( + ntsa::Error::invalid()); + + ntsa::SocketOption sendBufferSizeOption; + sendBufferSizeOption.makeSendBufferSize(100500); + ntsa::SocketOption rcvBufferSizeOption; + rcvBufferSizeOption.makeReceiveBufferSize(100500); + + socketMock + ->expect_getOption(doNotCare, + ntsa::SocketOptionType::e_SEND_BUFFER_SIZE) + .willOnce() + .willReturn(ntsa::Error()) + .setArg1(sendBufferSizeOption); + + socketMock + ->expect_getOption(doNotCare, + ntsa::SocketOptionType::e_RECEIVE_BUFFER_SIZE) + .willOnce() + .willReturn(ntsa::Error()) + .setArg1(rcvBufferSizeOption); + + socketMock->expect_maxBuffersPerSend().willOnce().willReturn(22); + socketMock->expect_maxBuffersPerReceive().willOnce().willReturn(22); + + reactorMock->expect_acquireHandleReservation_WillAlwaysReturn(true); + reactorMock->expect_releaseHandleReservation_WillAlwaysReturn(); + + socket->open(ntsa::Transport::e_TCP_IPV4_STREAM, socketMock); NTCI_LOG_DEBUG("Connection initiation..."); @@ -4723,7 +5765,7 @@ NTCCFG_TEST_CASE(22) const bsl::string epName = "unreachable.bbg.com"; - socket.connect(epName, connectOptions, connectCallback); + socket->connect(epName, connectOptions, connectCallback); NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); @@ -4742,7 +5784,15 @@ NTCCFG_TEST_CASE(22) connectRetryTimerMock->expect_close_WillOnceReturn(ntsa::Error()); reactorMock->expect_execute_WillOnceReturn(); - socket.shutdown(ntsa::ShutdownType::e_BOTH, + reactorMock->expect_detachSocket_WillOnceReturn( + socket, + bdlb::NullOptType::makeInitialValue(), + ntsa::Error::invalid()); + //TODO: is that ok to detach socket that has not been attached? + + socketMock->expect_close().willOnce().willReturn(ntsa::Error()); + + socket->shutdown(ntsa::ShutdownType::e_BOTH, ntsa::ShutdownMode::e_GRACEFUL); const auto callback = reactorMock->extract_execute_functor(); From 4718de2e04c56b52f6ca2898c918e31a6ce3ef46 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Thu, 21 Mar 2024 19:26:51 +0200 Subject: [PATCH 06/60] Update close mocked method of ntci::Timer --- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 105 ++++++++++++++++++++---- 1 file changed, 89 insertions(+), 16 deletions(-) diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index 7dd65e86..f1104eb6 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1794,7 +1794,7 @@ class StreamSocketMock : public ntsi::StreamSocket struct Invocation_close { private: struct InvocationData { - int d_expectedCalls; + int d_expectedCalls; bdlb::NullableValue d_result; InvocationData() @@ -3467,12 +3467,7 @@ class TimerMock : public ntci::Timer } ntsa::Error close() override { - if (d_close_result.isNull()) { - UNEXPECTED_CALL(); - } - const auto res = d_close_result.value(); - d_close_result.reset(); - return res; + return d_close_invocation.invoke(); } void arrive(const bsl::shared_ptr& self, const bsls::TimeInterval& now, @@ -3647,17 +3642,92 @@ class TimerMock : public ntci::Timer return d_schedule_invocation.expect(arg1, arg2); } - void expect_close_WillOnceReturn(const ntsa::Error& error) + struct Invocation_close { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_result; + + InvocationData() + : d_expectedCalls(0) + , d_result() + { + } + }; + + public: + Invocation_close& expect() + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + return *this; + } + Invocation_close& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_close& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_close& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + ntsa::Error invoke() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_close& expect_close() { - d_close_result = error; + return d_close_invocation.expect(); } private: bsl::shared_ptr dummyStrand; - bdlb::NullableValue d_close_result; - Invocation_schedule d_schedule_invocation; + Invocation_close d_close_invocation; }; } // close namespace mock @@ -5781,7 +5851,8 @@ NTCCFG_TEST_CASE(22) NTCI_LOG_DEBUG("Shutdown socket while it is waiting for remote " "endpoint resolution"); - connectRetryTimerMock->expect_close_WillOnceReturn(ntsa::Error()); + connectRetryTimerMock->expect_close().willOnce().willReturn( + ntsa::Error()); reactorMock->expect_execute_WillOnceReturn(); reactorMock->expect_detachSocket_WillOnceReturn( @@ -5793,7 +5864,7 @@ NTCCFG_TEST_CASE(22) socketMock->expect_close().willOnce().willReturn(ntsa::Error()); socket->shutdown(ntsa::ShutdownType::e_BOTH, - ntsa::ShutdownMode::e_GRACEFUL); + ntsa::ShutdownMode::e_GRACEFUL); const auto callback = reactorMock->extract_execute_functor(); callback(); @@ -5906,7 +5977,8 @@ NTCCFG_TEST_CASE(23) NTCI_LOG_DEBUG( "Shutdown socket while it is waiting for connection result"); - connectRetryTimerMock->expect_close_WillOnceReturn(ntsa::Error()); + connectRetryTimerMock->expect_close().willOnce().willReturn( + ntsa::Error()); reactorMock->expect_detachSocket_WillOnceReturn( socket, @@ -6056,8 +6128,9 @@ NTCCFG_TEST_CASE(24) "Shutdown socket while it is waiting for connection result"); { - connectRetryTimerMock->expect_close_WillOnceReturn(ntsa::Error()); - connectDeadlineTimerMock->expect_close_WillOnceReturn( + connectRetryTimerMock->expect_close().willOnce().willReturn( + ntsa::Error()); + connectDeadlineTimerMock->expect_close().willOnce().willReturn( ntsa::Error()); reactorMock->expect_detachSocket_WillOnceReturn(socket, From e5e70d851cc8fefe0e939e4a93fc65c65f792df1 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Thu, 21 Mar 2024 19:43:56 +0200 Subject: [PATCH 07/60] Inject socket mock in TC 23 --- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 187 +++++++++++++++++++++++- 1 file changed, 180 insertions(+), 7 deletions(-) diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index f1104eb6..ecdb4e51 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1624,8 +1624,7 @@ class StreamSocketMock : public ntsi::StreamSocket } ntsa::Error connect(const ntsa::Endpoint& endpoint) override { - UNEXPECTED_CALL(); - return ntsa::Error(); + return d_invocation_connect.invoke(endpoint); } ntsa::Error send(ntsa::SendContext* context, const bdlbb::Blob& data, @@ -2252,12 +2251,14 @@ class StreamSocketMock : public ntsi::StreamSocket bdlb::NullableValue d_arg1; bdlb::NullableValue d_result; ntsa::Endpoint** d_arg1_out; + bdlb::NullableValue d_arg1_set; InvocationData() : d_expectedCalls(0) , d_arg1() , d_result() , d_arg1_out(0) + , d_arg1_set() { } }; @@ -2311,6 +2312,14 @@ class StreamSocketMock : public ntsi::StreamSocket return *this; } + Invocation_sourceEndpoint& setArg1(const ntsa::Endpoint& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_set = arg1; + return *this; + } + ntsa::Error invoke(ntsa::Endpoint* arg1) { NTCCFG_TEST_FALSE(d_invocations.empty()); @@ -2328,6 +2337,10 @@ class StreamSocketMock : public ntsi::StreamSocket *invocation.d_arg1_out = arg1; } + if (invocation.d_arg1_set.has_value()) { + *arg1 = invocation.d_arg1_set.value(); + } + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); const auto result = invocation.d_result.value(); @@ -2601,6 +2614,112 @@ class StreamSocketMock : public ntsi::StreamSocket return d_invocation_getOption.expect(arg1, arg2); } + struct Invocation_connect { + private: + struct InvocationData { + int d_expectedCalls; + bdlb::NullableValue d_arg1; + bdlb::NullableValue d_result; + ntsa::Endpoint* d_arg1_out; + + InvocationData() + : d_expectedCalls(0) + , d_arg1() + , d_result() + , d_arg1_out(0) + { + } + }; + + public: + Invocation_connect& expect( + const bdlb::NullableValue& arg1) + { + d_invocations.emplace_back(); + InvocationData& invocation = d_invocations.back(); + + invocation.d_arg1 = arg1; + + return *this; + } + Invocation_connect& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *this; + } + Invocation_connect& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + InvocationData& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *this; + } + // Invocation_createTimer& times(int val){} //TODO: multiple calls + + Invocation_connect& willReturn(ntsa::Error result) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_result = result; + return *this; + } + + Invocation_connect& saveArg1(ntsa::Endpoint& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.back(); + invocation.d_arg1_out = &arg1; + return *this; + } + + ntsa::Error invoke(const ntsa::Endpoint& arg1) + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + InvocationData& invocation = d_invocations.front(); + + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } + + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + d_invocations.pop_front(); + } + } + + return result; + } + + private: + bsl::list d_invocations; + }; + + Invocation_connect& expect_connect( + const bdlb::NullableValue& arg1) + { + return d_invocation_connect.expect(arg1); + } + private: mutable Invocation_handle d_invocation_handle; mutable Invocation_close d_invocation_close; @@ -2611,6 +2730,7 @@ class StreamSocketMock : public ntsi::StreamSocket mutable Invocation_getOption d_invocation_getOption; mutable Invocation_sourceEndpoint d_invocation_sourceEndpoint; mutable Invocation_remoteEndpoint d_invocation_remoteEndpoint; + mutable Invocation_connect d_invocation_connect; }; class DataPoolMock : public ntci::DataPool @@ -5770,6 +5890,8 @@ NTCCFG_TEST_CASE(22) nullMetrics, &ta); + NTCI_LOG_DEBUG("Inject mocked ntsi::StreamSocket"); + socketMock->expect_handle().willAlways().willReturn(handle); socketMock->expect_setBlocking(false).willOnce().willReturn( ntsa::Error()); @@ -5883,7 +6005,8 @@ NTCCFG_TEST_CASE(23) { NTCI_LOG_DEBUG("Fixture setup, socket creation..."); - const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + const ntsa::Handle handle = 22; bdlb::NullableValue connectResult; @@ -5935,6 +6058,47 @@ NTCCFG_TEST_CASE(23) nullMetrics, &ta); + NTCI_LOG_DEBUG("Inject mocked ntsi::StreamSocket"); + + socketMock->expect_handle().willAlways().willReturn(handle); + socketMock->expect_setBlocking(false).willOnce().willReturn( + ntsa::Error()); + socketMock->expect_setBlocking(false).willOnce().willReturn( + ntsa::Error()); //TODO: for some reason it is called twice + socketMock->expect_setOption(doNotCare).willAlways().willReturn( + ntsa::Error()); + socketMock->expect_sourceEndpoint(doNotCare).willOnce().willReturn( + ntsa::Error::invalid()); + socketMock->expect_remoteEndpoint(doNotCare).willOnce().willReturn( + ntsa::Error::invalid()); + + ntsa::SocketOption sendBufferSizeOption; + sendBufferSizeOption.makeSendBufferSize(100500); + ntsa::SocketOption rcvBufferSizeOption; + rcvBufferSizeOption.makeReceiveBufferSize(100500); + + socketMock + ->expect_getOption(doNotCare, + ntsa::SocketOptionType::e_SEND_BUFFER_SIZE) + .willOnce() + .willReturn(ntsa::Error()) + .setArg1(sendBufferSizeOption); + + socketMock + ->expect_getOption(doNotCare, + ntsa::SocketOptionType::e_RECEIVE_BUFFER_SIZE) + .willOnce() + .willReturn(ntsa::Error()) + .setArg1(rcvBufferSizeOption); + + socketMock->expect_maxBuffersPerSend().willOnce().willReturn(22); + socketMock->expect_maxBuffersPerReceive().willOnce().willReturn(22); + + reactorMock->expect_acquireHandleReservation_WillAlwaysReturn(true); + reactorMock->expect_releaseHandleReservation_WillAlwaysReturn(); + + socket->open(ntsa::Transport::e_TCP_IPV4_STREAM, socketMock); + NTCI_LOG_DEBUG("Connection initiation..."); bsl::shared_ptr connectRetryTimerMock; @@ -5959,17 +6123,24 @@ NTCCFG_TEST_CASE(23) const ntca::ConnectOptions connectOptions; - const ntsa::Endpoint ep{"127.0.0.1:1234"}; + const ntsa::Endpoint targetEp{"127.0.0.1:1234"}; + const ntsa::Endpoint sourceEp{"127.0.0.1:22"}; - socket->connect(ep, connectOptions, connectCallback); + socket->connect(targetEp, connectOptions, connectCallback); NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); - reactorMock->expect_acquireHandleReservation_WillAlwaysReturn(true); - reactorMock->expect_releaseHandleReservation_WillAlwaysReturn(); reactorMock->expect_attachSocket_WillOnceReturn(socket, ntsa::Error()); reactorMock->expect_showWritable_WillOnceReturn(socket, ntsa::Error()); + socketMock->expect_connect(targetEp).willOnce().willReturn( + ntsa::Error()); + + socketMock->expect_sourceEndpoint(doNotCare) + .willOnce() + .willReturn(ntsa::Error()) + .setArg1(sourceEp); + ntca::TimerEvent timerEvent; timerEvent.setType(ntca::TimerEventType::e_DEADLINE); retryTimerCallback(connectRetryTimerMock, timerEvent, nullStrand); @@ -5985,6 +6156,8 @@ NTCCFG_TEST_CASE(23) bdlb::NullOptType::makeInitialValue(), ntsa::Error()); + socketMock->expect_close().willOnce().willReturn(ntsa::Error()); + socket->shutdown(ntsa::ShutdownType::e_BOTH, ntsa::ShutdownMode::e_GRACEFUL); From 3268d3454606884917d518651abde1d97158b20c Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Fri, 22 Mar 2024 18:07:24 +0200 Subject: [PATCH 08/60] code --- groups/ntc/ntccfg/ntccfg_test.h | 113 ++++++++ groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 366 +----------------------- 2 files changed, 127 insertions(+), 352 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index 28bfcffc..e362cc2c 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -822,3 +822,116 @@ class TestAllocator : public bslma::Allocator #else #error Not implemented #endif + +//#define NTF_MOCK_METHOD_INVOKE_COMMON_IMP(unused) \ + + +#define NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ + public: \ + Invocation_##METHOD_NAME& expect() \ + { \ + d_invocations.emplace_back(); \ + InvocationData& invocation = d_invocations.back(); \ + return *this; \ + } \ + Invocation_##METHOD_NAME& willOnce() \ + { \ + NTCCFG_TEST_FALSE(d_invocations.empty()); \ + \ + InvocationData& invocation = d_invocations.back(); \ + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); \ + \ + invocation.d_expectedCalls = 1; \ + return *this; \ + } \ + Invocation_##METHOD_NAME& willAlways() \ + { \ + NTCCFG_TEST_FALSE(d_invocations.empty()); \ + \ + InvocationData& invocation = d_invocations.back(); \ + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); \ + \ + invocation.d_expectedCalls = -1; \ + return *this; \ + } \ + \ + Invocation_##METHOD_NAME& willReturn(const RESULT& result) \ + { \ + NTCCFG_TEST_FALSE(d_invocations.empty()); \ + InvocationData& invocation = d_invocations.back(); \ + invocation.d_result = result; \ + return *this; \ + } \ + \ + private: \ + bsl::list d_invocations; + +#define NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) \ + public: \ + class Invocation_##METHOD_NAME \ + { \ + private: \ + struct InvocationData { \ + int d_expectedCalls; \ + bdlb::NullableValue d_result; \ + \ + InvocationData() \ + : d_expectedCalls(0) \ + , d_result() \ + { \ + } \ + }; \ + \ + NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ + \ + public: \ + RESULT invoke() \ + { \ + NTCCFG_TEST_FALSE(d_invocations.empty()); \ + InvocationData& invocation = d_invocations.front(); \ + \ + if (invocation.d_expectedCalls != -1) { \ + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); \ + } \ + \ + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); \ + const auto result = invocation.d_result.value(); \ + if (invocation.d_expectedCalls != -1) { \ + --invocation.d_expectedCalls; \ + if (invocation.d_expectedCalls == 0) { \ + d_invocations.pop_front(); \ + } \ + } \ + return result; \ + } \ + }; \ + \ + Invocation_##METHOD_NAME& expect_##METHOD_NAME() \ + { \ + return d_invocation_##METHOD_NAME.expect(); \ + } \ + \ + private: \ + mutable Invocation_##METHOD_NAME d_invocation_##METHOD_NAME; + +#define NTF_MOCK_METHOD_0(RESULT, METHOD_NAME) \ + public: \ + RESULT METHOD_NAME() override \ + { \ + return d_invocation_##METHOD_NAME.invoke(); \ + } \ + NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) + +#define NTF_MOCK_METHOD_0_CONST(RESULT, METHOD_NAME) \ + public: \ + RESULT METHOD_NAME() const override \ + { \ + return d_invocation_##METHOD_NAME.invoke(); \ + } \ + NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) + +#define NTF_MOCK_METHOD(RESULT, METHOD_NAME) \ + NTF_MOCK_METHOD_0(RESULT, METHOD_NAME) + +#define NTF_MOCK_METHOD_CONST(RESULT, METHOD_NAME) \ + NTF_MOCK_METHOD_0_CONST(RESULT, METHOD_NAME) \ No newline at end of file diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index ecdb4e51..bce1d2d7 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1591,10 +1591,8 @@ class BufferFactoryMock : public bdlbb::BlobBufferFactory class StreamSocketMock : public ntsi::StreamSocket { public: - ntsa::Handle handle() const override - { - return d_invocation_handle.invoke(); - } + NTF_MOCK_METHOD_CONST(ntsa::Handle, handle) + ntsa::Error open(ntsa::Transport::Value transport) override { UNEXPECTED_CALL(); @@ -1605,11 +1603,10 @@ class StreamSocketMock : public ntsi::StreamSocket UNEXPECTED_CALL(); return ntsa::Error(); } - ntsa::Handle release() override - { - UNEXPECTED_CALL(); - return 0; - } + + NTF_MOCK_METHOD(ntsa::Handle, release) + public: + ntsa::Error bind(const ntsa::Endpoint& endpoint, bool reuseAddress) override { @@ -1665,15 +1662,11 @@ class StreamSocketMock : public ntsi::StreamSocket UNEXPECTED_CALL(); return ntsa::Error(); } - ntsa::Error unlink() override - { - UNEXPECTED_CALL(); - return ntsa::Error(); - } - ntsa::Error close() override - { - return d_invocation_close.invoke(); - } + + NTF_MOCK_METHOD(ntsa::Error, unlink) + NTF_MOCK_METHOD(ntsa::Error, close) + public: + ntsa::Error sourceEndpoint(ntsa::Endpoint* result) const override { return d_invocation_sourceEndpoint.invoke(result); @@ -1700,338 +1693,11 @@ class StreamSocketMock : public ntsi::StreamSocket UNEXPECTED_CALL(); return ntsa::Error(); } - size_t maxBuffersPerSend() const override - { - return d_invocation_maxBuffersPerSend.invoke(); - } - size_t maxBuffersPerReceive() const override - { - return d_invocation_maxBuffersPerReceive.invoke(); - } - - struct Invocation_handle { - private: - struct InvocationData { - int d_expectedCalls; - bdlb::NullableValue d_result; - - InvocationData() - : d_expectedCalls(0) - , d_result() - { - } - }; - - public: - Invocation_handle& expect() - { - d_invocations.emplace_back(); - InvocationData& invocation = d_invocations.back(); - return *this; - } - Invocation_handle& willOnce() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = 1; - return *this; - } - Invocation_handle& willAlways() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = -1; - return *this; - } - // Invocation_createTimer& times(int val){} //TODO: multiple calls - - Invocation_handle& willReturn(ntsa::Handle result) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.back(); - invocation.d_result = result; - return *this; - } - - ntsa::Handle invoke() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.front(); - - if (invocation.d_expectedCalls != -1) { - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); - } - - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - d_invocations.pop_front(); - } - } - - return result; - } - - private: - bsl::list d_invocations; - }; - - Invocation_handle& expect_handle() - { - return d_invocation_handle.expect(); - } - - struct Invocation_close { - private: - struct InvocationData { - int d_expectedCalls; - bdlb::NullableValue d_result; - - InvocationData() - : d_expectedCalls(0) - , d_result() - { - } - }; - - public: - Invocation_close& expect() - { - d_invocations.emplace_back(); - InvocationData& invocation = d_invocations.back(); - return *this; - } - Invocation_close& willOnce() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = 1; - return *this; - } - Invocation_close& willAlways() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = -1; - return *this; - } - // Invocation_createTimer& times(int val){} //TODO: multiple calls - - Invocation_close& willReturn(ntsa::Error result) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.back(); - invocation.d_result = result; - return *this; - } - - ntsa::Error invoke() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.front(); - - if (invocation.d_expectedCalls != -1) { - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); - } - - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - d_invocations.pop_front(); - } - } - - return result; - } - - private: - bsl::list d_invocations; - }; - - Invocation_close& expect_close() - { - return d_invocation_close.expect(); - } - - struct Invocation_maxBuffersPerSend { - private: - struct InvocationData { - int d_expectedCalls; - bdlb::NullableValue d_result; - - InvocationData() - : d_expectedCalls(0) - , d_result() - { - } - }; - - public: - Invocation_maxBuffersPerSend& expect() - { - d_invocations.emplace_back(); - InvocationData& invocation = d_invocations.back(); - return *this; - } - Invocation_maxBuffersPerSend& willOnce() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = 1; - return *this; - } - Invocation_maxBuffersPerSend& willAlways() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = -1; - return *this; - } - // Invocation_createTimer& times(int val){} //TODO: multiple calls - - Invocation_maxBuffersPerSend& willReturn(bsl::size_t result) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.back(); - invocation.d_result = result; - return *this; - } - bsl::size_t invoke() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.front(); - - if (invocation.d_expectedCalls != -1) { - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); - } - - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - d_invocations.pop_front(); - } - } - - return result; - } + NTF_MOCK_METHOD_0_CONST(bsl::size_t, maxBuffersPerSend) + NTF_MOCK_METHOD_0_CONST(bsl::size_t, maxBuffersPerReceive) - private: - bsl::list d_invocations; - }; - - Invocation_maxBuffersPerSend& expect_maxBuffersPerSend() - { - return d_invocation_maxBuffersPerSend.expect(); - } - - struct Invocation_maxBuffersPerReceive { - private: - struct InvocationData { - int d_expectedCalls; - bdlb::NullableValue d_result; - - InvocationData() - : d_expectedCalls(0) - , d_result() - { - } - }; - - public: - Invocation_maxBuffersPerReceive& expect() - { - d_invocations.emplace_back(); - InvocationData& invocation = d_invocations.back(); - return *this; - } - Invocation_maxBuffersPerReceive& willOnce() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = 1; - return *this; - } - Invocation_maxBuffersPerReceive& willAlways() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = -1; - return *this; - } - // Invocation_createTimer& times(int val){} //TODO: multiple calls - - Invocation_maxBuffersPerReceive& willReturn(bsl::size_t result) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.back(); - invocation.d_result = result; - return *this; - } - - bsl::size_t invoke() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.front(); - - if (invocation.d_expectedCalls != -1) { - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); - } - - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - d_invocations.pop_front(); - } - } - - return result; - } - - private: - bsl::list d_invocations; - }; - - Invocation_maxBuffersPerReceive& expect_maxBuffersPerReceive() - { - return d_invocation_maxBuffersPerReceive.expect(); - } + public: struct Invocation_setBlocking { private: @@ -2721,10 +2387,6 @@ class StreamSocketMock : public ntsi::StreamSocket } private: - mutable Invocation_handle d_invocation_handle; - mutable Invocation_close d_invocation_close; - mutable Invocation_maxBuffersPerSend d_invocation_maxBuffersPerSend; - mutable Invocation_maxBuffersPerReceive d_invocation_maxBuffersPerReceive; mutable Invocation_setBlocking d_invocation_setBlocking; mutable Invocation_setOption d_invocation_setOption; mutable Invocation_getOption d_invocation_getOption; From bae1fec394d233f8418a1380567bb840197eb5ab Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Tue, 26 Mar 2024 13:32:55 +0200 Subject: [PATCH 09/60] Dynamically deduce number of argumens in macro call --- groups/ntc/ntccfg/ntccfg_test.h | 117 +++++++++++++++++++----- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 11 ++- 2 files changed, 101 insertions(+), 27 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index e362cc2c..732753ac 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -823,8 +823,20 @@ class TestAllocator : public bslma::Allocator #error Not implemented #endif -//#define NTF_MOCK_METHOD_INVOKE_COMMON_IMP(unused) \ - +#define NTF_MOCK_METHOD_INVOKE_COMMON_IMP() \ + NTCCFG_TEST_FALSE(d_invocations.empty()); \ + InvocationData& invocation = d_invocations.front(); \ + if (invocation.d_expectedCalls != -1) { \ + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); \ + } \ + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); \ + const auto result = invocation.d_result.value(); \ + if (invocation.d_expectedCalls != -1) { \ + --invocation.d_expectedCalls; \ + if (invocation.d_expectedCalls == 0) { \ + d_invocations.pop_front(); \ + } \ + } #define NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ public: \ @@ -887,21 +899,7 @@ class TestAllocator : public bslma::Allocator public: \ RESULT invoke() \ { \ - NTCCFG_TEST_FALSE(d_invocations.empty()); \ - InvocationData& invocation = d_invocations.front(); \ - \ - if (invocation.d_expectedCalls != -1) { \ - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); \ - } \ - \ - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); \ - const auto result = invocation.d_result.value(); \ - if (invocation.d_expectedCalls != -1) { \ - --invocation.d_expectedCalls; \ - if (invocation.d_expectedCalls == 0) { \ - d_invocations.pop_front(); \ - } \ - } \ + NTF_MOCK_METHOD_INVOKE_COMMON_IMP() \ return result; \ } \ }; \ @@ -922,7 +920,7 @@ class TestAllocator : public bslma::Allocator } \ NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) -#define NTF_MOCK_METHOD_0_CONST(RESULT, METHOD_NAME) \ +#define NTF_MOCK_METHOD_CONST_0(RESULT, METHOD_NAME) \ public: \ RESULT METHOD_NAME() const override \ { \ @@ -930,8 +928,83 @@ class TestAllocator : public bslma::Allocator } \ NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) -#define NTF_MOCK_METHOD(RESULT, METHOD_NAME) \ - NTF_MOCK_METHOD_0(RESULT, METHOD_NAME) -#define NTF_MOCK_METHOD_CONST(RESULT, METHOD_NAME) \ - NTF_MOCK_METHOD_0_CONST(RESULT, METHOD_NAME) \ No newline at end of file + +#define NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) \ + public: \ + class Invocation_##METHOD_NAME \ + { \ + private: \ + struct InvocationData { \ + int d_expectedCalls; \ + bdlb::NullableValue d_result; \ + bdlb::NullableValue d_arg1; \ + ARG1* d_arg1_out; \ + InvocationData() \ + : d_expectedCalls(0) \ + , d_result() \ + , d_arg1 \ + { \ + } \ + }; \ + \ + NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ + \ + Invocation_##METHOD_NAME& saveArg1To(ARG1& arg1) \ + { \ + NTCCFG_TEST_FALSE(d_invocations.empty()); \ + InvocationData& invocation = d_invocations.back(); \ + invocation.d_arg1_out = &arg1; \ + return *this; \ + } \ + \ + public: \ + RESULT invoke(const ARG1& arg1) \ + { \ + NTF_MOCK_METHOD_INVOKE_COMMON_IMP() \ + if (invocation.d_arg1.has_value()) { \ + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); \ + } \ + if (invocation.d_arg1_out) { \ + *invocation.d_arg1_out = arg1; \ + } \ + return result; \ + } \ + }; \ + \ + Invocation_##METHOD_NAME& expect_##METHOD_NAME() \ + { \ + return d_invocation_##METHOD_NAME.expect(); \ + } \ + \ + private: \ + mutable Invocation_##METHOD_NAME d_invocation_##METHOD_NAME; + +#define NTF_MOCK_METHOD_1(RESULT, METHOD_NAME, ARG1) \ + public: \ + /*TODO: invoke and correctly pass the argument, saving all CVs*/ \ + RESULT METHOD_NAME(ARG1 arg1) override \ + { \ + return d_invocation_##METHOD_NAME.invoke(arg1); \ + } \ + NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) + +#define NTF_MOCK_METHOD_1_CONST(RESULT, METHOD_NAME, ARG1) \ + public: \ + RESULT METHOD_NAME(ARG1 arg1) const override \ + { \ + return d_invocation_##METHOD_NAME.invoke(arg1); \ + } \ + NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1 + +#define NTF_EXPAND( X ) X +#define NTF_CAT( A, B ) A ## B +#define NTF_SELECT( NAME, NUM ) NTF_CAT( NAME ## _, NUM ) + +#define NTF_GET_COUNT( _1, _2, _3, _4, _5, _6, COUNT, ... ) COUNT +#define NTF_VA_SIZE( ... ) NTF_EXPAND( NTF_GET_COUNT( __VA_ARGS__, 4, 3, 2, 1, 0, -1 ) ) + +#define NTF_VA_SELECT( NAME, ... ) NTF_SELECT( NAME, NTF_VA_SIZE(__VA_ARGS__) )(__VA_ARGS__) + +#define NTF_MOCK_METHOD( ... ) NTF_VA_SELECT( NTF_MOCK_METHOD, __VA_ARGS__ ) +#define NTF_MOCK_METHOD_CONST( ... ) NTF_VA_SELECT( NTF_MOCK_METHOD_CONST, __VA_ARGS__ ) \ No newline at end of file diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index bce1d2d7..e9af847b 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1604,7 +1604,8 @@ class StreamSocketMock : public ntsi::StreamSocket return ntsa::Error(); } - NTF_MOCK_METHOD(ntsa::Handle, release) + NTF_MOCK_METHOD(ntsa::Handle, release); + public: ntsa::Error bind(const ntsa::Endpoint& endpoint, @@ -1694,8 +1695,8 @@ class StreamSocketMock : public ntsi::StreamSocket return ntsa::Error(); } - NTF_MOCK_METHOD_0_CONST(bsl::size_t, maxBuffersPerSend) - NTF_MOCK_METHOD_0_CONST(bsl::size_t, maxBuffersPerReceive) + NTF_MOCK_METHOD_CONST(bsl::size_t, maxBuffersPerSend) + NTF_MOCK_METHOD_CONST(bsl::size_t, maxBuffersPerReceive) public: @@ -5645,7 +5646,7 @@ NTCCFG_TEST_CASE(22) ntsa::Error::invalid()); //TODO: is that ok to detach socket that has not been attached? - socketMock->expect_close().willOnce().willReturn(ntsa::Error()); +// socketMock->expect_close().willOnce().willReturn(ntsa::Error()); socket->shutdown(ntsa::ShutdownType::e_BOTH, ntsa::ShutdownMode::e_GRACEFUL); @@ -5818,7 +5819,7 @@ NTCCFG_TEST_CASE(23) bdlb::NullOptType::makeInitialValue(), ntsa::Error()); - socketMock->expect_close().willOnce().willReturn(ntsa::Error()); +// socketMock->expect_close().willOnce().willReturn(ntsa::Error()); socket->shutdown(ntsa::ShutdownType::e_BOTH, ntsa::ShutdownMode::e_GRACEFUL); From 80af0b1e4ce9c75eaa242fe389a94a5d00269e64 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Tue, 26 Mar 2024 17:37:28 +0200 Subject: [PATCH 10/60] Mock more methods --- groups/ntc/ntccfg/ntccfg_test.h | 54 ++++++++++++++++--------- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 18 ++------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index 732753ac..41d7da68 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -839,13 +839,6 @@ class TestAllocator : public bslma::Allocator } #define NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ - public: \ - Invocation_##METHOD_NAME& expect() \ - { \ - d_invocations.emplace_back(); \ - InvocationData& invocation = d_invocations.back(); \ - return *this; \ - } \ Invocation_##METHOD_NAME& willOnce() \ { \ NTCCFG_TEST_FALSE(d_invocations.empty()); \ @@ -894,6 +887,14 @@ class TestAllocator : public bslma::Allocator } \ }; \ \ + public: \ + Invocation_##METHOD_NAME& expect() \ + { \ + d_invocations.emplace_back(); \ + InvocationData& invocation = d_invocations.back(); \ + return *this; \ + } \ + \ NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ \ public: \ @@ -928,8 +929,6 @@ class TestAllocator : public bslma::Allocator } \ NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) - - #define NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) \ public: \ class Invocation_##METHOD_NAME \ @@ -943,11 +942,22 @@ class TestAllocator : public bslma::Allocator InvocationData() \ : d_expectedCalls(0) \ , d_result() \ - , d_arg1 \ + , d_arg1() \ + , d_arg1_out(0) \ { \ } \ }; \ \ + public: \ + Invocation_##METHOD_NAME& expect( \ + const bdlb::NullableValue& arg1) \ + { \ + d_invocations.emplace_back(); \ + InvocationData& invocation = d_invocations.back(); \ + invocation.d_arg1 = arg1; \ + return *this; \ + } \ + \ NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ \ Invocation_##METHOD_NAME& saveArg1To(ARG1& arg1) \ @@ -972,9 +982,10 @@ class TestAllocator : public bslma::Allocator } \ }; \ \ - Invocation_##METHOD_NAME& expect_##METHOD_NAME() \ + Invocation_##METHOD_NAME& expect_##METHOD_NAME( \ + const bdlb::NullableValue& arg1) \ { \ - return d_invocation_##METHOD_NAME.expect(); \ + return d_invocation_##METHOD_NAME.expect(arg1); \ } \ \ private: \ @@ -997,14 +1008,17 @@ class TestAllocator : public bslma::Allocator } \ NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1 -#define NTF_EXPAND( X ) X -#define NTF_CAT( A, B ) A ## B -#define NTF_SELECT( NAME, NUM ) NTF_CAT( NAME ## _, NUM ) +#define NTF_EXPAND(X) X +#define NTF_CAT(A, B) A##B +#define NTF_SELECT(NAME, NUM) NTF_CAT(NAME##_, NUM) -#define NTF_GET_COUNT( _1, _2, _3, _4, _5, _6, COUNT, ... ) COUNT -#define NTF_VA_SIZE( ... ) NTF_EXPAND( NTF_GET_COUNT( __VA_ARGS__, 4, 3, 2, 1, 0, -1 ) ) +#define NTF_GET_COUNT(_1, _2, _3, _4, _5, _6, COUNT, ...) COUNT +#define NTF_VA_SIZE(...) \ + NTF_EXPAND(NTF_GET_COUNT(__VA_ARGS__, 4, 3, 2, 1, 0, -1)) -#define NTF_VA_SELECT( NAME, ... ) NTF_SELECT( NAME, NTF_VA_SIZE(__VA_ARGS__) )(__VA_ARGS__) +#define NTF_VA_SELECT(NAME, ...) \ + NTF_SELECT(NAME, NTF_VA_SIZE(__VA_ARGS__))(__VA_ARGS__) -#define NTF_MOCK_METHOD( ... ) NTF_VA_SELECT( NTF_MOCK_METHOD, __VA_ARGS__ ) -#define NTF_MOCK_METHOD_CONST( ... ) NTF_VA_SELECT( NTF_MOCK_METHOD_CONST, __VA_ARGS__ ) \ No newline at end of file +#define NTF_MOCK_METHOD(...) NTF_VA_SELECT(NTF_MOCK_METHOD, __VA_ARGS__) +#define NTF_MOCK_METHOD_CONST(...) \ + NTF_VA_SELECT(NTF_MOCK_METHOD_CONST, __VA_ARGS__) \ No newline at end of file diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index e9af847b..f0daa4cf 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1592,18 +1592,8 @@ class StreamSocketMock : public ntsi::StreamSocket { public: NTF_MOCK_METHOD_CONST(ntsa::Handle, handle) - - ntsa::Error open(ntsa::Transport::Value transport) override - { - UNEXPECTED_CALL(); - return ntsa::Error(); - } - ntsa::Error acquire(ntsa::Handle handle) override - { - UNEXPECTED_CALL(); - return ntsa::Error(); - } - + NTF_MOCK_METHOD(ntsa::Error, open, ntsa::Transport::Value) + NTF_MOCK_METHOD(ntsa::Error, acquire, ntsa::Handle) NTF_MOCK_METHOD(ntsa::Handle, release); public: @@ -5646,7 +5636,7 @@ NTCCFG_TEST_CASE(22) ntsa::Error::invalid()); //TODO: is that ok to detach socket that has not been attached? -// socketMock->expect_close().willOnce().willReturn(ntsa::Error()); + socketMock->expect_close().willOnce().willReturn(ntsa::Error()); socket->shutdown(ntsa::ShutdownType::e_BOTH, ntsa::ShutdownMode::e_GRACEFUL); @@ -5819,7 +5809,7 @@ NTCCFG_TEST_CASE(23) bdlb::NullOptType::makeInitialValue(), ntsa::Error()); -// socketMock->expect_close().willOnce().willReturn(ntsa::Error()); + socketMock->expect_close().willOnce().willReturn(ntsa::Error()); socket->shutdown(ntsa::ShutdownType::e_BOTH, ntsa::ShutdownMode::e_GRACEFUL); From c94625ce2048ee39b86b58937a2d05b8b3d4a524 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Wed, 27 Mar 2024 16:04:22 +0200 Subject: [PATCH 11/60] use templates where possible --- groups/ntc/ntccfg/ntccfg_test.h | 362 ++++++++++++++---------- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 51 ++-- 2 files changed, 233 insertions(+), 180 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index 41d7da68..1e71f378 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -823,95 +823,224 @@ class TestAllocator : public bslma::Allocator #error Not implemented #endif -#define NTF_MOCK_METHOD_INVOKE_COMMON_IMP() \ - NTCCFG_TEST_FALSE(d_invocations.empty()); \ - InvocationData& invocation = d_invocations.front(); \ - if (invocation.d_expectedCalls != -1) { \ - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); \ - } \ - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); \ - const auto result = invocation.d_result.value(); \ - if (invocation.d_expectedCalls != -1) { \ - --invocation.d_expectedCalls; \ - if (invocation.d_expectedCalls == 0) { \ - d_invocations.pop_front(); \ - } \ +#include +#include + +namespace framework { +namespace internal { + +template +struct InvocationResult { + BloombergLP::bdlb::NullableValue d_result; + + InvocationResult() + : d_result() + { } +}; -#define NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ - Invocation_##METHOD_NAME& willOnce() \ - { \ - NTCCFG_TEST_FALSE(d_invocations.empty()); \ - \ - InvocationData& invocation = d_invocations.back(); \ - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); \ - \ - invocation.d_expectedCalls = 1; \ - return *this; \ - } \ - Invocation_##METHOD_NAME& willAlways() \ - { \ - NTCCFG_TEST_FALSE(d_invocations.empty()); \ - \ - InvocationData& invocation = d_invocations.back(); \ - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); \ - \ - invocation.d_expectedCalls = -1; \ - return *this; \ - } \ - \ - Invocation_##METHOD_NAME& willReturn(const RESULT& result) \ +template <> +struct InvocationResult { + InvocationResult() + { + } +}; + +template +struct InvocationArg1 { + BloombergLP::bdlb::NullableValue d_arg1; + ARG1* d_arg1_out; + + InvocationArg1() + : d_arg1() + , d_arg1_out(0) + { + } +}; + +template +struct InvocationDataArg0 : public InvocationResult { + int d_expectedCalls; + InvocationDataArg0() + : d_expectedCalls(0) + { + } +}; + +template +struct InvocationDataArg1 : public InvocationResult, + public InvocationArg1 { + int d_expectedCalls; + InvocationDataArg1() + : d_expectedCalls(0) + { + } +}; + +template +class InvocationBaseWillReturn +{ + public: + virtual INVOCATION_DATA& getInvocationDataBack() = 0; + + SELF& willReturn(const RESULT& result) + { + INVOCATION_DATA& invocation = getInvocationDataBack(); + invocation.d_result = result; + return *(static_cast(this)); + } +}; + +template +class InvocationBaseWillReturn +{ + public: + virtual INVOCATION_DATA& getInvocationDataBack() = 0; +}; + +template +class InvocationBase +: public InvocationBaseWillReturn +{ + public: + SELF& willOnce() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + INVOCATION_DATA& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = 1; + return *(static_cast(this)); + } + SELF& willAlways() + { + NTCCFG_TEST_FALSE(d_invocations.empty()); + + INVOCATION_DATA& invocation = d_invocations.back(); + NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); + + invocation.d_expectedCalls = -1; + return *(static_cast(this)); + } + + INVOCATION_DATA& getInvocationDataBack() override + { + NTCCFG_TEST_FALSE(this->d_invocations.empty()); + return d_invocations.back(); + } + + public: + bsl::list d_invocations; +}; + +template +class Invocation0 : public InvocationBase, + Invocation0, + RESULT> +{ + typedef InvocationDataArg0 InvocationDataImpl; + + public: + Invocation0& expect() + { + this->d_invocations.emplace_back(); + InvocationDataImpl& invocation = this->d_invocations.back(); + return *this; + } + + RESULT invoke() + { + NTCCFG_TEST_FALSE(this->d_invocations.empty()); + InvocationDataImpl& invocation = this->d_invocations.front(); + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + this->d_invocations.pop_front(); + } + } + return result; + } +}; + +template +class Invocation1 : public InvocationBase, + Invocation1, + RESULT> +{ + typedef InvocationDataArg1 InvocationDataImpl; + + public: + Invocation1& expect( + const BloombergLP::bdlb::NullableValue& arg1) + { + this->d_invocations.emplace_back(); + InvocationDataImpl& invocation = this->d_invocations.back(); + // TODO: save arg1 + return *this; + } + + RESULT invoke(const ARG1& arg1) + { + NTCCFG_TEST_FALSE(this->d_invocations.empty()); + InvocationDataImpl& invocation = this->d_invocations.front(); + if (invocation.d_expectedCalls != -1) { + NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); + } + //TODO: match arg1 + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + this->d_invocations.pop_front(); + } + } + return result; + } +}; + +} +} + +#define NTF_EXPAND(X) X +#define NTF_CAT(A, B) A##B +#define NTF_SELECT(NAME, NUM) NTF_CAT(NAME##_, NUM) + +#define NTF_GET_COUNT(_1, _2, _3, _4, _5, _6, COUNT, ...) COUNT +#define NTF_VA_SIZE(...) \ + NTF_EXPAND(NTF_GET_COUNT(__VA_ARGS__, 4, 3, 2, 1, 0, -1)) + +#define NTF_VA_SELECT(NAME, ...) \ + NTF_SELECT(NAME, NTF_VA_SIZE(__VA_ARGS__))(__VA_ARGS__) + +#define NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) \ + public: \ + framework::internal::Invocation0& expect_##METHOD_NAME() \ { \ - NTCCFG_TEST_FALSE(d_invocations.empty()); \ - InvocationData& invocation = d_invocations.back(); \ - invocation.d_result = result; \ - return *this; \ + return d_invocation_##METHOD_NAME.expect(); \ } \ \ private: \ - bsl::list d_invocations; + mutable framework::internal::Invocation0 \ + d_invocation_##METHOD_NAME; -#define NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) \ +#define NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) \ public: \ - class Invocation_##METHOD_NAME \ - { \ - private: \ - struct InvocationData { \ - int d_expectedCalls; \ - bdlb::NullableValue d_result; \ - \ - InvocationData() \ - : d_expectedCalls(0) \ - , d_result() \ - { \ - } \ - }; \ - \ - public: \ - Invocation_##METHOD_NAME& expect() \ - { \ - d_invocations.emplace_back(); \ - InvocationData& invocation = d_invocations.back(); \ - return *this; \ - } \ - \ - NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ - \ - public: \ - RESULT invoke() \ - { \ - NTF_MOCK_METHOD_INVOKE_COMMON_IMP() \ - return result; \ - } \ - }; \ - \ - Invocation_##METHOD_NAME& expect_##METHOD_NAME() \ + framework::internal::Invocation1& expect_##METHOD_NAME( \ + const bdlb::NullableValue& arg1) \ { \ - return d_invocation_##METHOD_NAME.expect(); \ + return d_invocation_##METHOD_NAME.expect(arg1); \ } \ \ private: \ - mutable Invocation_##METHOD_NAME d_invocation_##METHOD_NAME; + mutable framework::internal::Invocation1 \ + d_invocation_##METHOD_NAME; #define NTF_MOCK_METHOD_0(RESULT, METHOD_NAME) \ public: \ @@ -929,96 +1058,23 @@ class TestAllocator : public bslma::Allocator } \ NTF_MOCK_METHOD_0_IMP(RESULT, METHOD_NAME) -#define NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) \ - public: \ - class Invocation_##METHOD_NAME \ - { \ - private: \ - struct InvocationData { \ - int d_expectedCalls; \ - bdlb::NullableValue d_result; \ - bdlb::NullableValue d_arg1; \ - ARG1* d_arg1_out; \ - InvocationData() \ - : d_expectedCalls(0) \ - , d_result() \ - , d_arg1() \ - , d_arg1_out(0) \ - { \ - } \ - }; \ - \ - public: \ - Invocation_##METHOD_NAME& expect( \ - const bdlb::NullableValue& arg1) \ - { \ - d_invocations.emplace_back(); \ - InvocationData& invocation = d_invocations.back(); \ - invocation.d_arg1 = arg1; \ - return *this; \ - } \ - \ - NTF_MOCK_METHOD_COMMON_IMP(RESULT, METHOD_NAME) \ - \ - Invocation_##METHOD_NAME& saveArg1To(ARG1& arg1) \ - { \ - NTCCFG_TEST_FALSE(d_invocations.empty()); \ - InvocationData& invocation = d_invocations.back(); \ - invocation.d_arg1_out = &arg1; \ - return *this; \ - } \ - \ - public: \ - RESULT invoke(const ARG1& arg1) \ - { \ - NTF_MOCK_METHOD_INVOKE_COMMON_IMP() \ - if (invocation.d_arg1.has_value()) { \ - NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); \ - } \ - if (invocation.d_arg1_out) { \ - *invocation.d_arg1_out = arg1; \ - } \ - return result; \ - } \ - }; \ - \ - Invocation_##METHOD_NAME& expect_##METHOD_NAME( \ - const bdlb::NullableValue& arg1) \ - { \ - return d_invocation_##METHOD_NAME.expect(arg1); \ - } \ - \ - private: \ - mutable Invocation_##METHOD_NAME d_invocation_##METHOD_NAME; - #define NTF_MOCK_METHOD_1(RESULT, METHOD_NAME, ARG1) \ public: \ - /*TODO: invoke and correctly pass the argument, saving all CVs*/ \ RESULT METHOD_NAME(ARG1 arg1) override \ { \ return d_invocation_##METHOD_NAME.invoke(arg1); \ } \ NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) -#define NTF_MOCK_METHOD_1_CONST(RESULT, METHOD_NAME, ARG1) \ +#define NTF_MOCK_METHOD_CONST_1(RESULT, METHOD_NAME, ARG1) \ public: \ RESULT METHOD_NAME(ARG1 arg1) const override \ { \ return d_invocation_##METHOD_NAME.invoke(arg1); \ } \ - NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1 - -#define NTF_EXPAND(X) X -#define NTF_CAT(A, B) A##B -#define NTF_SELECT(NAME, NUM) NTF_CAT(NAME##_, NUM) - -#define NTF_GET_COUNT(_1, _2, _3, _4, _5, _6, COUNT, ...) COUNT -#define NTF_VA_SIZE(...) \ - NTF_EXPAND(NTF_GET_COUNT(__VA_ARGS__, 4, 3, 2, 1, 0, -1)) - -#define NTF_VA_SELECT(NAME, ...) \ - NTF_SELECT(NAME, NTF_VA_SIZE(__VA_ARGS__))(__VA_ARGS__) + NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) #define NTF_MOCK_METHOD(...) NTF_VA_SELECT(NTF_MOCK_METHOD, __VA_ARGS__) + #define NTF_MOCK_METHOD_CONST(...) \ NTF_VA_SELECT(NTF_MOCK_METHOD_CONST, __VA_ARGS__) \ No newline at end of file diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index f0daa4cf..13685ba5 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1582,10 +1582,12 @@ class ResolverMock : public ntci::Resolver class BufferFactoryMock : public bdlbb::BlobBufferFactory { public: - void allocate(bdlbb::BlobBuffer* buffer) override - { - UNEXPECTED_CALL(); - } + void allocate(bdlbb::BlobBuffer* buffer) override + { + UNEXPECTED_CALL(); + } + +// NTF_MOCK_METHOD(void, allocate, bdlbb::BlobBuffer*) }; class StreamSocketMock : public ntsi::StreamSocket @@ -1597,7 +1599,6 @@ class StreamSocketMock : public ntsi::StreamSocket NTF_MOCK_METHOD(ntsa::Handle, release); public: - ntsa::Error bind(const ntsa::Endpoint& endpoint, bool reuseAddress) override { @@ -1657,7 +1658,6 @@ class StreamSocketMock : public ntsi::StreamSocket NTF_MOCK_METHOD(ntsa::Error, unlink) NTF_MOCK_METHOD(ntsa::Error, close) public: - ntsa::Error sourceEndpoint(ntsa::Endpoint* result) const override { return d_invocation_sourceEndpoint.invoke(result); @@ -1689,7 +1689,6 @@ class StreamSocketMock : public ntsi::StreamSocket NTF_MOCK_METHOD_CONST(bsl::size_t, maxBuffersPerReceive) public: - struct Invocation_setBlocking { private: struct InvocationData { @@ -2378,12 +2377,12 @@ class StreamSocketMock : public ntsi::StreamSocket } private: - mutable Invocation_setBlocking d_invocation_setBlocking; - mutable Invocation_setOption d_invocation_setOption; - mutable Invocation_getOption d_invocation_getOption; - mutable Invocation_sourceEndpoint d_invocation_sourceEndpoint; - mutable Invocation_remoteEndpoint d_invocation_remoteEndpoint; - mutable Invocation_connect d_invocation_connect; + mutable Invocation_setBlocking d_invocation_setBlocking; + mutable Invocation_setOption d_invocation_setOption; + mutable Invocation_getOption d_invocation_getOption; + mutable Invocation_sourceEndpoint d_invocation_sourceEndpoint; + mutable Invocation_remoteEndpoint d_invocation_remoteEndpoint; + mutable Invocation_connect d_invocation_connect; }; class DataPoolMock : public ntci::DataPool @@ -5490,8 +5489,8 @@ NTCCFG_TEST_CASE(22) { NTCI_LOG_DEBUG("Fixture setup, socket creation..."); - const auto doNotCare = bdlb::NullOptType::makeInitialValue(); - const ntsa::Handle handle = 22; + const bsl::nullopt_t doNotCare = bsl::nullopt; + const ntsa::Handle handle = 22; bdlb::NullableValue connectResult; @@ -5614,10 +5613,9 @@ NTCCFG_TEST_CASE(22) NTCI_LOG_DEBUG("Trigger internal timer to initiate connection..."); - resolverMock->expect_getEndpoint_WillOnceReturn( - epName, - bdlb::NullOptType::makeInitialValue(), - ntsa::Error()); + resolverMock->expect_getEndpoint_WillOnceReturn(epName, + doNotCare, + ntsa::Error()); ntca::TimerEvent timerEvent; timerEvent.setType(ntca::TimerEventType::e_DEADLINE); @@ -5632,7 +5630,7 @@ NTCCFG_TEST_CASE(22) reactorMock->expect_detachSocket_WillOnceReturn( socket, - bdlb::NullOptType::makeInitialValue(), + doNotCare, ntsa::Error::invalid()); //TODO: is that ok to detach socket that has not been attached? @@ -5658,8 +5656,8 @@ NTCCFG_TEST_CASE(23) { NTCI_LOG_DEBUG("Fixture setup, socket creation..."); - const auto doNotCare = bdlb::NullOptType::makeInitialValue(); - const ntsa::Handle handle = 22; + const bsl::nullopt_t doNotCare = bsl::nullopt; + const ntsa::Handle handle = 22; bdlb::NullableValue connectResult; @@ -5804,10 +5802,9 @@ NTCCFG_TEST_CASE(23) connectRetryTimerMock->expect_close().willOnce().willReturn( ntsa::Error()); - reactorMock->expect_detachSocket_WillOnceReturn( - socket, - bdlb::NullOptType::makeInitialValue(), - ntsa::Error()); + reactorMock->expect_detachSocket_WillOnceReturn(socket, + doNotCare, + ntsa::Error()); socketMock->expect_close().willOnce().willReturn(ntsa::Error()); @@ -5838,7 +5835,7 @@ NTCCFG_TEST_CASE(24) { NTCI_LOG_DEBUG("Fixture setup, socket creation..."); - const auto doNotCare = bdlb::NullOptType::makeInitialValue(); + const bsl::nullopt_t doNotCare = bsl::nullopt; bdlb::NullableValue connectResult; From 38d879d67243f13c0fd3f30d596b7b643c511e1b Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Wed, 27 Mar 2024 16:06:23 +0200 Subject: [PATCH 12/60] process arg1 --- groups/ntc/ntccfg/ntccfg_test.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index 1e71f378..2f8a71fc 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -981,7 +981,7 @@ class Invocation1 : public InvocationBase, { this->d_invocations.emplace_back(); InvocationDataImpl& invocation = this->d_invocations.back(); - // TODO: save arg1 + invocation.d_arg1 = arg1; return *this; } @@ -992,7 +992,12 @@ class Invocation1 : public InvocationBase, if (invocation.d_expectedCalls != -1) { NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); } - //TODO: match arg1 + if (invocation.d_arg1.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); + } + if (invocation.d_arg1_out) { + *invocation.d_arg1_out = arg1; + } NTCCFG_TEST_TRUE(invocation.d_result.has_value()); const auto result = invocation.d_result.value(); if (invocation.d_expectedCalls != -1) { From 191b2b41b26768627b1eb9660c07a83f39aeda4d Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Wed, 27 Mar 2024 19:00:00 +0200 Subject: [PATCH 13/60] handle void return result correctly --- groups/ntc/ntccfg/ntccfg_test.h | 111 +++++++++++++++++------- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 19 +++- 2 files changed, 93 insertions(+), 37 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index 2f8a71fc..38354006 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -861,7 +861,7 @@ struct InvocationArg1 { template struct InvocationDataArg0 : public InvocationResult { int d_expectedCalls; - InvocationDataArg0() + InvocationDataArg0() : d_expectedCalls(0) { } @@ -871,7 +871,7 @@ template struct InvocationDataArg1 : public InvocationResult, public InvocationArg1 { int d_expectedCalls; - InvocationDataArg1() + InvocationDataArg1() : d_expectedCalls(0) { } @@ -898,16 +898,57 @@ class InvocationBaseWillReturn virtual INVOCATION_DATA& getInvocationDataBack() = 0; }; -template -class InvocationBase -: public InvocationBaseWillReturn +template +class InvocationBaseInvoke { public: - SELF& willOnce() + RESULT finalizeInvocation() { - NTCCFG_TEST_FALSE(d_invocations.empty()); + INVOCATION_DATA& invocation = this->getInvocationDataFront(); + NTCCFG_TEST_TRUE(invocation.d_result.has_value()); + const auto result = invocation.d_result.value(); + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + this->removeInvocationDataFront(); + } + } + return result; + } + private: + virtual INVOCATION_DATA& getInvocationDataFront() = 0; + virtual void removeInvocationDataFront() = 0; +}; - INVOCATION_DATA& invocation = d_invocations.back(); +template +class InvocationBaseInvoke +{ + public: + void finalizeInvocation() + { + INVOCATION_DATA& invocation = this->getInvocationDataFront(); + if (invocation.d_expectedCalls != -1) { + --invocation.d_expectedCalls; + if (invocation.d_expectedCalls == 0) { + this->removeInvocationDataFront(); + } + } + } + + private: + virtual INVOCATION_DATA& getInvocationDataFront() = 0; + virtual void removeInvocationDataFront() = 0; +}; + + + +template +class InvocationBaseOnceAlways +{ + public: + SELF& willOnce() + { + INVOCATION_DATA& invocation = this->getInvocationDataBack(); NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); invocation.d_expectedCalls = 1; @@ -915,22 +956,42 @@ class InvocationBase } SELF& willAlways() { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - INVOCATION_DATA& invocation = d_invocations.back(); + INVOCATION_DATA& invocation = this->getInvocationDataBack(); NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); invocation.d_expectedCalls = -1; return *(static_cast(this)); } + private: + virtual INVOCATION_DATA& getInvocationDataBack() = 0; +}; + +template +class InvocationBase +: public InvocationBaseWillReturn, + public InvocationBaseOnceAlways, + public InvocationBaseInvoke +{ + protected: INVOCATION_DATA& getInvocationDataBack() override { NTCCFG_TEST_FALSE(this->d_invocations.empty()); return d_invocations.back(); } - public: + INVOCATION_DATA& getInvocationDataFront() override + { + NTCCFG_TEST_FALSE(this->d_invocations.empty()); + return d_invocations.front(); + } + + void removeInvocationDataFront() override + { + NTCCFG_TEST_FALSE(this->d_invocations.empty()); + d_invocations.pop_front(); + } + bsl::list d_invocations; }; @@ -942,10 +1003,9 @@ class Invocation0 : public InvocationBase, typedef InvocationDataArg0 InvocationDataImpl; public: - Invocation0& expect() + Invocation0& expect() { this->d_invocations.emplace_back(); - InvocationDataImpl& invocation = this->d_invocations.back(); return *this; } @@ -956,15 +1016,8 @@ class Invocation0 : public InvocationBase, if (invocation.d_expectedCalls != -1) { NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); } - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - this->d_invocations.pop_front(); - } - } - return result; + + return this->finalizeInvocation(); } }; @@ -976,7 +1029,7 @@ class Invocation1 : public InvocationBase, typedef InvocationDataArg1 InvocationDataImpl; public: - Invocation1& expect( + Invocation1& expect( const BloombergLP::bdlb::NullableValue& arg1) { this->d_invocations.emplace_back(); @@ -998,15 +1051,7 @@ class Invocation1 : public InvocationBase, if (invocation.d_arg1_out) { *invocation.d_arg1_out = arg1; } - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - this->d_invocations.pop_front(); - } - } - return result; + return this->finalizeInvocation(); } }; diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index 13685ba5..1f94157a 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1583,11 +1583,22 @@ class BufferFactoryMock : public bdlbb::BlobBufferFactory { public: void allocate(bdlbb::BlobBuffer* buffer) override - { - UNEXPECTED_CALL(); - } + { + UNEXPECTED_CALL(); + } -// NTF_MOCK_METHOD(void, allocate, bdlbb::BlobBuffer*) + // NTF_MOCK_METHOD(void, allocate, bdlbb::BlobBuffer*) +}; + +struct MyClass +{ + virtual void doSmth(int) = 0; +}; + +class MyClassMock : public MyClass +{ +public: + NTF_MOCK_METHOD_1(void, doSmth, int); }; class StreamSocketMock : public ntsi::StreamSocket From 98dada60fe0c36225308eefcd5c8456be61771c5 Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Thu, 28 Mar 2024 13:21:53 +0200 Subject: [PATCH 14/60] Save ARG1 correctly (remove_cvref) --- groups/ntc/ntccfg/ntccfg_test.h | 18 +- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 291 +++--------------------- 2 files changed, 42 insertions(+), 267 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index 38354006..269e382e 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -824,6 +824,7 @@ class TestAllocator : public bslma::Allocator #endif #include +#include #include namespace framework { @@ -848,8 +849,9 @@ struct InvocationResult { template struct InvocationArg1 { - BloombergLP::bdlb::NullableValue d_arg1; - ARG1* d_arg1_out; + typedef typename bsl::remove_cvref::type ARG1_type; + BloombergLP::bdlb::NullableValue d_arg1; + ARG1_type* d_arg1_out; InvocationArg1() : d_arg1() @@ -915,6 +917,7 @@ class InvocationBaseInvoke } return result; } + private: virtual INVOCATION_DATA& getInvocationDataFront() = 0; virtual void removeInvocationDataFront() = 0; @@ -940,8 +943,6 @@ class InvocationBaseInvoke virtual void removeInvocationDataFront() = 0; }; - - template class InvocationBaseOnceAlways { @@ -1029,8 +1030,9 @@ class Invocation1 : public InvocationBase, typedef InvocationDataArg1 InvocationDataImpl; public: - Invocation1& expect( - const BloombergLP::bdlb::NullableValue& arg1) + typedef typename bsl::remove_cvref::type ARG1_type; + + Invocation1& expect(const BloombergLP::bdlb::NullableValue& arg1) { this->d_invocations.emplace_back(); InvocationDataImpl& invocation = this->d_invocations.back(); @@ -1038,7 +1040,7 @@ class Invocation1 : public InvocationBase, return *this; } - RESULT invoke(const ARG1& arg1) + RESULT invoke(const ARG1_type& arg1) { NTCCFG_TEST_FALSE(this->d_invocations.empty()); InvocationDataImpl& invocation = this->d_invocations.front(); @@ -1083,7 +1085,7 @@ class Invocation1 : public InvocationBase, #define NTF_MOCK_METHOD_1_IMP(RESULT, METHOD_NAME, ARG1) \ public: \ framework::internal::Invocation1& expect_##METHOD_NAME( \ - const bdlb::NullableValue& arg1) \ + const bdlb::NullableValue::type>& arg1) \ { \ return d_invocation_##METHOD_NAME.expect(arg1); \ } \ diff --git a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp index 1f94157a..5cbaa05b 100644 --- a/groups/ntc/ntcr/ntcr_streamsocket.t.cpp +++ b/groups/ntc/ntcr/ntcr_streamsocket.t.cpp @@ -1582,24 +1582,19 @@ class ResolverMock : public ntci::Resolver class BufferFactoryMock : public bdlbb::BlobBufferFactory { public: - void allocate(bdlbb::BlobBuffer* buffer) override - { - UNEXPECTED_CALL(); - } - - // NTF_MOCK_METHOD(void, allocate, bdlbb::BlobBuffer*) + NTF_MOCK_METHOD(void, allocate, bdlbb::BlobBuffer*) }; -struct MyClass -{ - virtual void doSmth(int) = 0; -}; - -class MyClassMock : public MyClass -{ -public: - NTF_MOCK_METHOD_1(void, doSmth, int); -}; +// struct MyClass +// { +// virtual void doSmth(const int&) = 0; +// }; +// +// class MyClassMock : public MyClass +// { +// public: +// NTF_MOCK_METHOD_1(void, doSmth, const int&); +// }; class StreamSocketMock : public ntsi::StreamSocket { @@ -1622,10 +1617,9 @@ class StreamSocketMock : public ntsi::StreamSocket UNEXPECTED_CALL(); return ntsa::Error(); } - ntsa::Error connect(const ntsa::Endpoint& endpoint) override - { - return d_invocation_connect.invoke(endpoint); - } + + NTF_MOCK_METHOD(ntsa::Error, connect, const ntsa::Endpoint&) + ntsa::Error send(ntsa::SendContext* context, const bdlbb::Blob& data, const ntsa::SendOptions& options) override @@ -1654,20 +1648,12 @@ class StreamSocketMock : public ntsi::StreamSocket UNEXPECTED_CALL(); return ntsa::Error(); } - ntsa::Error receiveNotifications( - ntsa::NotificationQueue* notifications) override - { - UNEXPECTED_CALL(); - return ntsa::Error(); - } - ntsa::Error shutdown(ntsa::ShutdownType::Value direction) override - { - UNEXPECTED_CALL(); - return ntsa::Error(); - } + NTF_MOCK_METHOD(ntsa::Error, receiveNotifications, ntsa::NotificationQueue*) + NTF_MOCK_METHOD(ntsa::Error, shutdown, ntsa::ShutdownType::Value) NTF_MOCK_METHOD(ntsa::Error, unlink) NTF_MOCK_METHOD(ntsa::Error, close) + public: ntsa::Error sourceEndpoint(ntsa::Endpoint* result) const override { @@ -1690,12 +1676,8 @@ class StreamSocketMock : public ntsi::StreamSocket { return d_invocation_getOption.invoke(option, type); } - ntsa::Error getLastError(ntsa::Error* result) override - { - UNEXPECTED_CALL(); - return ntsa::Error(); - } + NTF_MOCK_METHOD(ntsa::Error, getLastError, ntsa::Error*) NTF_MOCK_METHOD_CONST(bsl::size_t, maxBuffersPerSend) NTF_MOCK_METHOD_CONST(bsl::size_t, maxBuffersPerReceive) @@ -2281,119 +2263,12 @@ class StreamSocketMock : public ntsi::StreamSocket return d_invocation_getOption.expect(arg1, arg2); } - struct Invocation_connect { - private: - struct InvocationData { - int d_expectedCalls; - bdlb::NullableValue d_arg1; - bdlb::NullableValue d_result; - ntsa::Endpoint* d_arg1_out; - - InvocationData() - : d_expectedCalls(0) - , d_arg1() - , d_result() - , d_arg1_out(0) - { - } - }; - - public: - Invocation_connect& expect( - const bdlb::NullableValue& arg1) - { - d_invocations.emplace_back(); - InvocationData& invocation = d_invocations.back(); - - invocation.d_arg1 = arg1; - - return *this; - } - Invocation_connect& willOnce() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = 1; - return *this; - } - Invocation_connect& willAlways() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = -1; - return *this; - } - // Invocation_createTimer& times(int val){} //TODO: multiple calls - - Invocation_connect& willReturn(ntsa::Error result) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.back(); - invocation.d_result = result; - return *this; - } - - Invocation_connect& saveArg1(ntsa::Endpoint& arg1) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.back(); - invocation.d_arg1_out = &arg1; - return *this; - } - - ntsa::Error invoke(const ntsa::Endpoint& arg1) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.front(); - - if (invocation.d_expectedCalls != -1) { - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); - } - - if (invocation.d_arg1.has_value()) { - NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); - } - - if (invocation.d_arg1_out) { - *invocation.d_arg1_out = arg1; - } - - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - d_invocations.pop_front(); - } - } - - return result; - } - - private: - bsl::list d_invocations; - }; - - Invocation_connect& expect_connect( - const bdlb::NullableValue& arg1) - { - return d_invocation_connect.expect(arg1); - } - private: mutable Invocation_setBlocking d_invocation_setBlocking; mutable Invocation_setOption d_invocation_setOption; mutable Invocation_getOption d_invocation_getOption; mutable Invocation_sourceEndpoint d_invocation_sourceEndpoint; mutable Invocation_remoteEndpoint d_invocation_remoteEndpoint; - mutable Invocation_connect d_invocation_connect; }; class DataPoolMock : public ntci::DataPool @@ -2404,6 +2279,7 @@ class DataPoolMock : public ntci::DataPool UNEXPECTED_CALL(); return bsl::shared_ptr(); } + bsl::shared_ptr createOutgoingData() override { if (d_createOutgoingData_result.isNull()) { @@ -3243,15 +3119,11 @@ class TimerMock : public ntci::Timer { return d_schedule_invocation.invoke(deadline, period); } - ntsa::Error cancel() override - { - UNEXPECTED_CALL(); - return ntsa::Error(); - } - ntsa::Error close() override - { - return d_close_invocation.invoke(); - } + + NTF_MOCK_METHOD(ntsa::Error, cancel) + NTF_MOCK_METHOD(ntsa::Error, close) +public: + void arrive(const bsl::shared_ptr& self, const bsls::TimeInterval& now, const bsls::TimeInterval& deadline) override @@ -3263,36 +3135,19 @@ class TimerMock : public ntci::Timer UNEXPECTED_CALL(); return nullptr; } - int id() const override - { - UNEXPECTED_CALL(); - return 0; - } - bool oneShot() const override - { - UNEXPECTED_CALL(); - return false; - } - bslmt::ThreadUtil::Handle threadHandle() const override - { - UNEXPECTED_CALL(); - return BloombergLP::bslmt::ThreadUtil::Handle(); - } - size_t threadIndex() const override - { - UNEXPECTED_CALL(); - return 0; - } + NTF_MOCK_METHOD_CONST(int, id) + NTF_MOCK_METHOD_CONST(bool, oneShot) + NTF_MOCK_METHOD_CONST(bslmt::ThreadUtil::Handle, threadHandle) + NTF_MOCK_METHOD_CONST(size_t, threadIndex) + +public: const bsl::shared_ptr& strand() const override { UNEXPECTED_CALL(); return dummyStrand; } - bsls::TimeInterval currentTime() const override - { - UNEXPECTED_CALL(); - return bsls::TimeInterval(); - } + NTF_MOCK_METHOD_CONST(bsls::TimeInterval, currentTime) +public: struct Invocation_schedule { // const bsls::TimeInterval& deadline, @@ -3425,92 +3280,10 @@ class TimerMock : public ntci::Timer return d_schedule_invocation.expect(arg1, arg2); } - struct Invocation_close { - private: - struct InvocationData { - int d_expectedCalls; - bdlb::NullableValue d_result; - - InvocationData() - : d_expectedCalls(0) - , d_result() - { - } - }; - - public: - Invocation_close& expect() - { - d_invocations.emplace_back(); - InvocationData& invocation = d_invocations.back(); - return *this; - } - Invocation_close& willOnce() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = 1; - return *this; - } - Invocation_close& willAlways() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - - InvocationData& invocation = d_invocations.back(); - NTCCFG_TEST_EQ(invocation.d_expectedCalls, 0); - - invocation.d_expectedCalls = -1; - return *this; - } - // Invocation_createTimer& times(int val){} //TODO: multiple calls - - Invocation_close& willReturn(ntsa::Error result) - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.back(); - invocation.d_result = result; - return *this; - } - - ntsa::Error invoke() - { - NTCCFG_TEST_FALSE(d_invocations.empty()); - InvocationData& invocation = d_invocations.front(); - - if (invocation.d_expectedCalls != -1) { - NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); - } - - NTCCFG_TEST_TRUE(invocation.d_result.has_value()); - const auto result = invocation.d_result.value(); - - if (invocation.d_expectedCalls != -1) { - --invocation.d_expectedCalls; - if (invocation.d_expectedCalls == 0) { - d_invocations.pop_front(); - } - } - - return result; - } - - private: - bsl::list d_invocations; - }; - - Invocation_close& expect_close() - { - return d_close_invocation.expect(); - } - private: bsl::shared_ptr dummyStrand; Invocation_schedule d_schedule_invocation; - Invocation_close d_close_invocation; }; } // close namespace mock From 3bda560bc86b577565e104ad953569d23d6f8a2b Mon Sep 17 00:00:00 2001 From: Sergey Mitrofanov Date: Tue, 2 Apr 2024 18:42:49 +0300 Subject: [PATCH 15/60] Save partially developed new approach to mocks --- groups/ntc/ntccfg/ntccfg_test.h | 573 +++++++++++++++++++++++- groups/ntc/ntcr/ntcr_streamsocket.t.cpp | 197 ++++++-- 2 files changed, 721 insertions(+), 49 deletions(-) diff --git a/groups/ntc/ntccfg/ntccfg_test.h b/groups/ntc/ntccfg/ntccfg_test.h index 269e382e..a8e3caf4 100644 --- a/groups/ntc/ntccfg/ntccfg_test.h +++ b/groups/ntc/ntccfg/ntccfg_test.h @@ -825,6 +825,7 @@ class TestAllocator : public bslma::Allocator #include #include +#include #include namespace framework { @@ -849,17 +850,90 @@ struct InvocationResult { template struct InvocationArg1 { - typedef typename bsl::remove_cvref::type ARG1_type; - BloombergLP::bdlb::NullableValue d_arg1; + typedef typename bsl::remove_cvref::type + ARG1_type; //TODO: do I need it? + + BloombergLP::bdlb::NullableValue d_arg1_exp; ARG1_type* d_arg1_out; InvocationArg1() - : d_arg1() + : d_arg1_exp() + , d_arg1_out(0) + { + } +}; + +template +struct InvocationArg1 { + // typedef typename bsl::remove_cvref::type ARG1_type; + // typedef typename bsl::remove_pointer::type ARG1_pure_type; + // + // BloombergLP::bdlb::NullableValue d_arg1_exp; + // BloombergLP::bdlb::NullableValue d_arg1_in; + // ARG1_type** d_arg1_out; + + typedef typename bsl::remove_pointer::type ARG1_pure_type; + + BloombergLP::bdlb::NullableValue d_arg1_exp; + BloombergLP::bdlb::NullableValue d_arg1_in; + ARG1** d_arg1_out; + + InvocationArg1() + : d_arg1_exp() + , d_arg1_in() , d_arg1_out(0) { } }; +template +struct InvocationArg1 { + typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_pointer::type ARG1_pure_type; + + BloombergLP::bdlb::NullableValue d_arg1_exp; + BloombergLP::bdlb::NullableValue d_arg1_in; + ARG1_type* d_arg1_out; + + InvocationArg1() + : d_arg1_exp() + , d_arg1_in() + , d_arg1_out(0) + { + } +}; + +/* +template +struct InvocationArg1 { + typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_pointer::type ARG1_pure_type; + + BloombergLP::bdlb::NullableValue d_arg1_exp; + ARG1_type* d_arg1_out; + + InvocationArg1() + : d_arg1_exp() + , d_arg1_out(0) + { + } +}; + +template +struct InvocationArg1 { + typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_pointer::type ARG1_pure_type; + + BloombergLP::bdlb::NullableValue d_arg1_exp; + ARG1_type* d_arg1_out; + + InvocationArg1() + : d_arg1_exp() + , d_arg1_out(0) + { + } +};*/ + template struct InvocationDataArg0 : public InvocationResult { int d_expectedCalls; @@ -968,11 +1042,18 @@ class InvocationBaseOnceAlways virtual INVOCATION_DATA& getInvocationDataBack() = 0; }; -template +struct NoArgProcessor { +}; + +template class InvocationBase : public InvocationBaseWillReturn, public InvocationBaseOnceAlways, - public InvocationBaseInvoke + public InvocationBaseInvoke, + public INVOCATION_ARG_PROCESSOR { protected: INVOCATION_DATA& getInvocationDataBack() override @@ -996,6 +1077,71 @@ class InvocationBase bsl::list d_invocations; }; +template +class InvocationArg1Processor +{ + public: + typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_pointer::type ARG1_pure_type; + + SELF& saveArg1(ARG1_type* arg1_out) + { + INVOCATION_DATA& invocation = this->getInvocationDataBack(); + invocation.d_arg1_out = arg1_out; + return *(static_cast(this)); + } + + virtual INVOCATION_DATA& getInvocationDataBack() = 0; +}; + +template +class InvocationArg1Processor +{ + typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_pointer::type ARG1_pure_type; + + public: + SELF& setArg1To(const ARG1_pure_type& arg1_in) + { + INVOCATION_DATA& invocation = this->getInvocationDataBack(); + invocation.d_arg1_in = arg1_in; + return *(static_cast(this)); + } + SELF& saveArg1(ARG1_type** arg1_out) + { + INVOCATION_DATA& invocation = this->getInvocationDataBack(); + invocation.d_arg1_out = arg1_out; + return *(static_cast(this)); + } + + protected: + virtual INVOCATION_DATA& getInvocationDataBack() = 0; +}; + +template +class InvocationArg1Processor +{ + typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_pointer::type ARG1_pure_type; + + public: + SELF& setArg1To(const ARG1_pure_type& arg1_in) + { + INVOCATION_DATA& invocation = this->getInvocationDataBack(); + invocation.d_arg1_in = arg1_in; + return *(static_cast(this)); + } + SELF& saveArg1(ARG1_type* arg1_out) + { + INVOCATION_DATA& invocation = this->getInvocationDataBack(); + invocation.d_arg1_out = arg1_out; + return *(static_cast(this)); + } + + protected: + virtual INVOCATION_DATA& getInvocationDataBack() = 0; +}; + template class Invocation0 : public InvocationBase, Invocation0, @@ -1023,36 +1169,54 @@ class Invocation0 : public InvocationBase, }; template -class Invocation1 : public InvocationBase, - Invocation1, - RESULT> +class Invocation1 +: public InvocationBase< + InvocationDataArg1, + Invocation1, + RESULT, + InvocationArg1Processor, + InvocationDataArg1, + ARG1> > { typedef InvocationDataArg1 InvocationDataImpl; public: - typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_cvref::type ARG1_type; + typedef typename bsl::remove_pointer::type ARG1_pure_type; - Invocation1& expect(const BloombergLP::bdlb::NullableValue& arg1) + Invocation1& expect( + const BloombergLP::bdlb::NullableValue& arg1) { this->d_invocations.emplace_back(); InvocationDataImpl& invocation = this->d_invocations.back(); - invocation.d_arg1 = arg1; + invocation.d_arg1_exp = arg1; return *this; } - RESULT invoke(const ARG1_type& arg1) + // Invocation1& setArg1To(const ARG1_pure_type& arg1In) + // { + // NTCCFG_TEST_FALSE(this->d_invocations.empty()); + // InvocationDataImpl& invocation = this->d_invocations.back(); + // invocation.d_arg1_in = arg1In; + // return *this; + // } + + RESULT invoke(ARG1 arg1) { NTCCFG_TEST_FALSE(this->d_invocations.empty()); InvocationDataImpl& invocation = this->d_invocations.front(); if (invocation.d_expectedCalls != -1) { NTCCFG_TEST_GE(invocation.d_expectedCalls, 1); } - if (invocation.d_arg1.has_value()) { - NTCCFG_TEST_EQ(arg1, invocation.d_arg1.value()); - } - if (invocation.d_arg1_out) { - *invocation.d_arg1_out = arg1; + if (invocation.d_arg1_exp.has_value()) { + NTCCFG_TEST_EQ(arg1, invocation.d_arg1_exp.value()); } + // if (invocation.d_arg1_out) { + // *invocation.d_arg1_out = arg1; + // } + // if (invocation.d_arg1_in.has_value()) { + // arg1 = invocation.d_arg1_in.value(); + // } return this->finalizeInvocation(); } }; @@ -1129,4 +1293,377 @@ class Invocation1 : public InvocationBase, #define NTF_MOCK_METHOD(...) NTF_VA_SELECT(NTF_MOCK_METHOD, __VA_ARGS__) #define NTF_MOCK_METHOD_CONST(...) \ - NTF_VA_SELECT(NTF_MOCK_METHOD_CONST, __VA_ARGS__) \ No newline at end of file + NTF_VA_SELECT(NTF_MOCK_METHOD_CONST, __VA_ARGS__) + +namespace NewMock { + +template +struct ProcessInterface { + virtual void process(const ARG& arg) = 0; + virtual ~ ProcessInterface() + { + } +}; + +template +struct DerefPolicy { + static void extract(const FROM& from, TO* to) + { + *to = *from; + } + // static void extract(const FROM* from, TO* to) + // { + // *to = *from; + // } +}; + +template +struct NoDerefPolicy { + static void extract(const FROM& from, TO* to) + { + *to = from; + } +}; + +template class EXTRACT_POLICY> +struct Extractor { + template + void process(const ARG& arg) + { + EXTRACT_POLICY::extract(arg, d_to); + } + // template + // void process(const ARG* arg) + // { + // EXTRACT_POLICY::extract(arg, d_to); + // } + + explicit Extractor(TO* to) + : d_to(to) + { + } + + TO* d_to; +}; + +template