Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions sdk/core/azure-core-amqp/test/ut/mock_amqp_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <azure/core/amqp/internal/network/socket_listener.hpp>
#include <azure/core/amqp/internal/session.hpp>

#include <atomic>
#include <memory>

#include <gtest/gtest.h>
Expand Down Expand Up @@ -57,8 +58,8 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {
public Azure::Core::Amqp::_internal::MessageSenderEvents {
public:
MockServiceEndpoint(std::string const& name, MockServiceEndpointOptions const& options)
: m_listenerContext{options.ListenerContext},
m_enableTrace{options.EnableTrace}, m_name{name}
: m_listenerContext{options.ListenerContext}, m_enableTrace{options.EnableTrace},
m_name{name}
{
}

Expand Down Expand Up @@ -185,6 +186,9 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {
sender.second->Close();
}
}
// Release link ownership before destroying sessions whose End can fail.
m_receiver.clear();
m_sender.clear();
}

protected:
Expand Down Expand Up @@ -625,6 +629,12 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {

void StopListening()
{
if (!m_listening)
{
return;
}
// A destructor must not retry a partially completed shutdown.
m_listening = false;
GTEST_LOG_(INFO) << "Stop listening";
// Cancel the listener context, which will cause any WaitForXxx calls to exit.

Expand All @@ -643,17 +653,31 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {
{
for (const auto& session : m_sessions)
{
session->End({});
try
{
session->End({});
}
catch (std::runtime_error const& ex)
{
if (m_peerClosed.load() && std::string(ex.what()) == "Could not end session")
{
GTEST_LOG_(INFO) << "Session End after the mock peer closed reported: "
<< ex.what();
}
else
{
ADD_FAILURE() << "Unexpected mock session shutdown failure: " << ex.what();
}
}
}
// Note: clearing the sessions list destroys the session and calls session_end always, so
// it does not need to be called here.
// A failed End still needs native destruction to release its polling reference.
m_sessions.clear();
}
for (const auto& connection : m_connections)
{
connection->Close({});
}
m_listening = false;
m_connections.clear();
}

// Closes the connections without closing the links on them first, which is the shape of a
Expand Down Expand Up @@ -721,6 +745,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {
if (newState == Azure::Core::Amqp::_internal::ConnectionState::End
|| newState == Azure::Core::Amqp::_internal::ConnectionState::Error)
{
m_peerClosed = true;
// If the connection is closed, then we should close the connection.
m_listenerContext.Cancel();
}
Expand Down Expand Up @@ -796,6 +821,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {

bool m_enableTrace{true};
bool m_listening{false};
std::atomic<bool> m_peerClosed{false};

std::string m_connectionId;
std::thread m_serverThread;
Expand Down
39 changes: 22 additions & 17 deletions sdk/core/azure-core-amqp/test/ut/session_cleanup_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {
}
return session_end(session, condition, description);
}

void RetryFailedEnd()
{
{
CleanupTestListener server;
_internal::ConnectionOptions options;
options.Port = server.GetPort();
_internal::Connection connection("localhost", nullptr, options);
auto session
= _detail::SessionFactory::CreateFromInternal(std::make_shared<_detail::SessionImpl>(
_detail::ConnectionFactory::GetImpl(connection),
_internal::SessionOptions{},
nullptr,
FailOnceEnd));
session.Begin({});
EXPECT_THROW(session.End({}), std::runtime_error);
EXPECT_NO_THROW(session.End("amqp:internal-error", "retry", {}));
EXPECT_THROW(session.End({}), std::runtime_error);
}
Common::_detail::GlobalStateHolder::GlobalStateInstance()->AssertIdle();
}
} // namespace

class SessionCleanupDeathTest : public ::testing::Test {
Expand Down Expand Up @@ -102,23 +123,7 @@ namespace Azure { namespace Core { namespace Amqp { namespace Tests {
{
EXPECT_EXIT(
{
{
CleanupTestListener server;
_internal::ConnectionOptions options;
options.Port = server.GetPort();
_internal::Connection connection("localhost", nullptr, options);
auto session = _detail::SessionFactory::CreateFromInternal(
std::make_shared<_detail::SessionImpl>(
_detail::ConnectionFactory::GetImpl(connection),
_internal::SessionOptions{},
nullptr,
FailOnceEnd));
session.Begin({});
EXPECT_THROW(session.End({}), std::runtime_error);
EXPECT_NO_THROW(session.End("amqp:internal-error", "retry", {}));
EXPECT_THROW(session.End({}), std::runtime_error);
}
Common::_detail::GlobalStateHolder::GlobalStateInstance()->AssertIdle();
RetryFailedEnd();
std::exit(::testing::Test::HasFailure() ? 1 : 0);
},
::testing::ExitedWithCode(0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,8 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test {
});
}
Amqp::Tests::MessageTests::AmqpServerMock server(AvailablePort());
server.AddServiceEndpoint(
std::make_shared<PropertiesEndpoint>(
false, pauseBeforeSend ? nullptr : &requestReceived));
server.AddServiceEndpoint(std::make_shared<PropertiesEndpoint>(
false, pauseBeforeSend ? nullptr : &requestReceived));
server.StartListening();
{
Amqp::_internal::ConnectionOptions options;
Expand Down Expand Up @@ -364,6 +363,8 @@ namespace Azure { namespace Messaging { namespace EventHubs { namespace Test {
EXPECT_EQ(endCalls.load(), 1);
}
server.StopListening();
server.StopListening();
Amqp::Common::_detail::GlobalStateHolder::GlobalStateInstance()->AssertIdle();
}
Azure::Core::Diagnostics::Logger::SetListener(nullptr);
EXPECT_EQ(closeFailureLogged.load(), cancelledClose);
Expand Down
Loading