From 821ad5570a48287fc3addf54e7d75c8177e92704 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 02:15:13 +0000
Subject: [PATCH 1/8] Initial plan
From fe74fb148dab06a6badfe18c99ac42a149457367 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 02:21:13 +0000
Subject: [PATCH 2/8] Initial exploration and planning
Co-authored-by: drewnoakes <350947+drewnoakes@users.noreply.github.com>
---
NuGet.Config | 3 +++
1 file changed, 3 insertions(+)
diff --git a/NuGet.Config b/NuGet.Config
index aad3952a3..271cba873 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -4,4 +4,7 @@
+
+
+
\ No newline at end of file
From f1757e8a1b2a9419e4fd6fc5e4a1afe6ef21163c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 02:22:15 +0000
Subject: [PATCH 3/8] Add INetMQMonitor interface and update NetMQMonitor to
implement it
Co-authored-by: drewnoakes <350947+drewnoakes@users.noreply.github.com>
---
src/NetMQ/Monitoring/INetMQMonitor.cs | 121 ++++++++++++++++++++++++++
src/NetMQ/Monitoring/NetMQMonitor.cs | 2 +-
2 files changed, 122 insertions(+), 1 deletion(-)
create mode 100644 src/NetMQ/Monitoring/INetMQMonitor.cs
diff --git a/src/NetMQ/Monitoring/INetMQMonitor.cs b/src/NetMQ/Monitoring/INetMQMonitor.cs
new file mode 100644
index 000000000..a205f30cf
--- /dev/null
+++ b/src/NetMQ/Monitoring/INetMQMonitor.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Threading.Tasks;
+
+namespace NetMQ.Monitoring
+{
+ ///
+ /// NetMQMonitor interface, implement to fake the NetMQMonitor in tests.
+ ///
+ public interface INetMQMonitor : IDisposable
+ {
+ ///
+ /// The monitoring address.
+ ///
+ string Endpoint { get; }
+
+ ///
+ /// Get whether this monitor is currently running.
+ ///
+ ///
+ /// Start the monitor running via either or .
+ /// Stop the monitor via either or .
+ ///
+ bool IsRunning { get; }
+
+ ///
+ /// Gets and sets the timeout interval for poll iterations when using and .
+ ///
+ ///
+ /// The higher the number the longer it may take the to stop the monitor.
+ /// This value has no effect when the monitor is run via .
+ ///
+ TimeSpan Timeout { get; set; }
+
+ ///
+ /// Raised whenever any monitored event fires.
+ ///
+ event EventHandler? EventReceived;
+
+ ///
+ /// Occurs when a connection is made to a socket.
+ ///
+ event EventHandler? Connected;
+
+ ///
+ /// Occurs when a synchronous connection attempt failed, and its completion is being polled for.
+ ///
+ event EventHandler? ConnectDelayed;
+
+ ///
+ /// Occurs when an asynchronous connect / reconnection attempt is being handled by a reconnect timer.
+ ///
+ event EventHandler? ConnectRetried;
+
+ ///
+ /// Occurs when a socket is bound to an address and is ready to accept connections.
+ ///
+ event EventHandler? Listening;
+
+ ///
+ /// Occurs when a socket could not bind to an address.
+ ///
+ event EventHandler? BindFailed;
+
+ ///
+ /// Occurs when a connection from a remote peer has been established with a socket's listen address.
+ ///
+ event EventHandler? Accepted;
+
+ ///
+ /// Occurs when a connection attempt to a socket's bound address fails.
+ ///
+ event EventHandler? AcceptFailed;
+
+ ///
+ /// Occurs when a connection was closed.
+ ///
+ event EventHandler? Closed;
+
+ ///
+ /// Occurs when a connection couldn't be closed.
+ ///
+ event EventHandler? CloseFailed;
+
+ ///
+ /// Occurs when the stream engine (TCP and IPC specific) detects a corrupted / broken session.
+ ///
+ event EventHandler? Disconnected;
+
+ ///
+ /// Add the monitor object to a NetMQPoller, register to to be signalled on new events
+ ///
+ ///
+ ///
+ ///
+ ///
+ void AttachToPoller(T poller) where T : INetMQPoller;
+
+ ///
+ /// Remove the monitor object from attached poller
+ ///
+ void DetachFromPoller();
+
+ ///
+ /// Start monitor the socket, the method doesn't start a new thread and will block until the monitor poll is stopped
+ ///
+ /// The Monitor must not have already started nor attached to a poller.
+ void Start();
+
+ ///
+ /// Start a background task for the monitoring operation.
+ ///
+ ///
+ Task StartAsync();
+
+ ///
+ /// Stop monitoring. Blocks until monitoring completed.
+ ///
+ /// If this monitor is attached to a poller you must detach it first and not use the stop method.
+ void Stop();
+ }
+}
diff --git a/src/NetMQ/Monitoring/NetMQMonitor.cs b/src/NetMQ/Monitoring/NetMQMonitor.cs
index bac778aac..30d74d26d 100644
--- a/src/NetMQ/Monitoring/NetMQMonitor.cs
+++ b/src/NetMQ/Monitoring/NetMQMonitor.cs
@@ -17,7 +17,7 @@ namespace NetMQ.Monitoring
/// - Call and .
///
///
- public class NetMQMonitor : IDisposable
+ public class NetMQMonitor : INetMQMonitor
{
private readonly NetMQSocket m_monitoringSocket;
private readonly bool m_ownsMonitoringSocket;
From 5ba4632576af105ab305ae67c3172fb06172210c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 02:24:58 +0000
Subject: [PATCH 4/8] Add test demonstrating INetMQMonitor mockability
Co-authored-by: drewnoakes <350947+drewnoakes@users.noreply.github.com>
---
src/NetMQ.Tests/NetMQMonitorTests.cs | 81 ++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/src/NetMQ.Tests/NetMQMonitorTests.cs b/src/NetMQ.Tests/NetMQMonitorTests.cs
index 81eb0d1d3..5f912bf5c 100644
--- a/src/NetMQ.Tests/NetMQMonitorTests.cs
+++ b/src/NetMQ.Tests/NetMQMonitorTests.cs
@@ -188,5 +188,86 @@ public void ConvertArgThrowsForInvalidType()
MonitorEvent monitorEvent = new MonitorEvent(SocketEvents.All, addr: "", arg: socket!);
Assert.Throws(() => monitorEvent.ConvertArg());
}
+
+ [Fact]
+ public void INetMQMonitorCanBeMocked()
+ {
+ // This test demonstrates that INetMQMonitor can be mocked for testing
+ var mockMonitor = new MockNetMQMonitor();
+
+ // Verify the mock implements the interface
+ INetMQMonitor monitor = mockMonitor;
+
+ Assert.NotNull(monitor);
+ Assert.Equal("mock://endpoint", monitor.Endpoint);
+ Assert.False(monitor.IsRunning);
+
+ // Verify we can subscribe to events
+ var eventReceived = false;
+ monitor.EventReceived += (s, e) => { eventReceived = true; };
+
+ // Trigger the event
+ mockMonitor.RaiseEventReceived();
+
+ Assert.True(eventReceived);
+ }
+
+ // Simple mock implementation to demonstrate INetMQMonitor is mockable
+ private class MockNetMQMonitor : INetMQMonitor
+ {
+ public string Endpoint => "mock://endpoint";
+ public bool IsRunning { get; private set; }
+ public TimeSpan Timeout { get; set; }
+
+ public event EventHandler? EventReceived;
+#pragma warning disable CS0067 // Event is never used - these are part of the interface contract
+ public event EventHandler? Connected;
+ public event EventHandler? ConnectDelayed;
+ public event EventHandler? ConnectRetried;
+ public event EventHandler? Listening;
+ public event EventHandler? BindFailed;
+ public event EventHandler? Accepted;
+ public event EventHandler? AcceptFailed;
+ public event EventHandler? Closed;
+ public event EventHandler? CloseFailed;
+ public event EventHandler? Disconnected;
+#pragma warning restore CS0067
+
+ public void AttachToPoller(T poller) where T : INetMQPoller
+ {
+ IsRunning = true;
+ }
+
+ public void DetachFromPoller()
+ {
+ IsRunning = false;
+ }
+
+ public void Start()
+ {
+ IsRunning = true;
+ }
+
+ public Task StartAsync()
+ {
+ IsRunning = true;
+ return Task.CompletedTask;
+ }
+
+ public void Stop()
+ {
+ IsRunning = false;
+ }
+
+ public void Dispose()
+ {
+ IsRunning = false;
+ }
+
+ public void RaiseEventReceived()
+ {
+ EventReceived?.Invoke(this, new NetMQMonitorSocketEventArgs(null!, "test", null!, SocketEvents.Connected));
+ }
+ }
}
}
From b6b048f8337d3c88f04691878ec2e6f7c99a19fa Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 02:44:46 +0000
Subject: [PATCH 5/8] Remove xunit package source and test mock implementation
per review feedback
Co-authored-by: drewnoakes <350947+drewnoakes@users.noreply.github.com>
---
NuGet.Config | 4 --
src/NetMQ.Tests/NetMQMonitorTests.cs | 81 ----------------------------
2 files changed, 85 deletions(-)
diff --git a/NuGet.Config b/NuGet.Config
index 271cba873..041e71acb 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -2,9 +2,5 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/NetMQ.Tests/NetMQMonitorTests.cs b/src/NetMQ.Tests/NetMQMonitorTests.cs
index 5f912bf5c..81eb0d1d3 100644
--- a/src/NetMQ.Tests/NetMQMonitorTests.cs
+++ b/src/NetMQ.Tests/NetMQMonitorTests.cs
@@ -188,86 +188,5 @@ public void ConvertArgThrowsForInvalidType()
MonitorEvent monitorEvent = new MonitorEvent(SocketEvents.All, addr: "", arg: socket!);
Assert.Throws(() => monitorEvent.ConvertArg());
}
-
- [Fact]
- public void INetMQMonitorCanBeMocked()
- {
- // This test demonstrates that INetMQMonitor can be mocked for testing
- var mockMonitor = new MockNetMQMonitor();
-
- // Verify the mock implements the interface
- INetMQMonitor monitor = mockMonitor;
-
- Assert.NotNull(monitor);
- Assert.Equal("mock://endpoint", monitor.Endpoint);
- Assert.False(monitor.IsRunning);
-
- // Verify we can subscribe to events
- var eventReceived = false;
- monitor.EventReceived += (s, e) => { eventReceived = true; };
-
- // Trigger the event
- mockMonitor.RaiseEventReceived();
-
- Assert.True(eventReceived);
- }
-
- // Simple mock implementation to demonstrate INetMQMonitor is mockable
- private class MockNetMQMonitor : INetMQMonitor
- {
- public string Endpoint => "mock://endpoint";
- public bool IsRunning { get; private set; }
- public TimeSpan Timeout { get; set; }
-
- public event EventHandler? EventReceived;
-#pragma warning disable CS0067 // Event is never used - these are part of the interface contract
- public event EventHandler? Connected;
- public event EventHandler? ConnectDelayed;
- public event EventHandler? ConnectRetried;
- public event EventHandler? Listening;
- public event EventHandler? BindFailed;
- public event EventHandler? Accepted;
- public event EventHandler? AcceptFailed;
- public event EventHandler? Closed;
- public event EventHandler? CloseFailed;
- public event EventHandler? Disconnected;
-#pragma warning restore CS0067
-
- public void AttachToPoller(T poller) where T : INetMQPoller
- {
- IsRunning = true;
- }
-
- public void DetachFromPoller()
- {
- IsRunning = false;
- }
-
- public void Start()
- {
- IsRunning = true;
- }
-
- public Task StartAsync()
- {
- IsRunning = true;
- return Task.CompletedTask;
- }
-
- public void Stop()
- {
- IsRunning = false;
- }
-
- public void Dispose()
- {
- IsRunning = false;
- }
-
- public void RaiseEventReceived()
- {
- EventReceived?.Invoke(this, new NetMQMonitorSocketEventArgs(null!, "test", null!, SocketEvents.Connected));
- }
- }
}
}
From dd640a45c4a5f8f7458cbb3ca09d8a9660890bcf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 02:55:13 +0000
Subject: [PATCH 6/8] Improve documentation: fix property docs, populate empty
elements, add periods, use cref, add inheritdoc
Co-authored-by: drewnoakes <350947+drewnoakes@users.noreply.github.com>
---
src/NetMQ/Monitoring/INetMQMonitor.cs | 26 ++++----
src/NetMQ/Monitoring/NetMQMonitor.cs | 91 ++++++---------------------
2 files changed, 32 insertions(+), 85 deletions(-)
diff --git a/src/NetMQ/Monitoring/INetMQMonitor.cs b/src/NetMQ/Monitoring/INetMQMonitor.cs
index a205f30cf..f84be436b 100644
--- a/src/NetMQ/Monitoring/INetMQMonitor.cs
+++ b/src/NetMQ/Monitoring/INetMQMonitor.cs
@@ -9,12 +9,12 @@ namespace NetMQ.Monitoring
public interface INetMQMonitor : IDisposable
{
///
- /// The monitoring address.
+ /// Gets the monitoring address.
///
string Endpoint { get; }
///
- /// Get whether this monitor is currently running.
+ /// Gets whether this monitor is currently running.
///
///
/// Start the monitor running via either or .
@@ -87,35 +87,35 @@ public interface INetMQMonitor : IDisposable
event EventHandler? Disconnected;
///
- /// Add the monitor object to a NetMQPoller, register to to be signalled on new events
+ /// Adds the monitor object to a NetMQPoller. Register to to be signalled on new events.
///
- ///
- ///
- ///
- ///
+ /// The poller to attach to.
+ /// The type of poller.
+ /// The is null.
+ /// The monitor is already started or already attached to a poller.
void AttachToPoller(T poller) where T : INetMQPoller;
///
- /// Remove the monitor object from attached poller
+ /// Removes the monitor object from the attached poller.
///
void DetachFromPoller();
///
- /// Start monitor the socket, the method doesn't start a new thread and will block until the monitor poll is stopped
+ /// Starts monitoring the socket. This method doesn't start a new thread and will block until the monitor poll is stopped.
///
/// The Monitor must not have already started nor attached to a poller.
void Start();
///
- /// Start a background task for the monitoring operation.
+ /// Starts a background task for the monitoring operation.
///
- ///
+ /// A task representing the monitoring operation.
Task StartAsync();
///
- /// Stop monitoring. Blocks until monitoring completed.
+ /// Stops monitoring. Blocks until monitoring completed.
///
- /// If this monitor is attached to a poller you must detach it first and not use the stop method.
+ /// If this monitor is attached to a poller you must detach it first and not use the method.
void Stop();
}
}
diff --git a/src/NetMQ/Monitoring/NetMQMonitor.cs b/src/NetMQ/Monitoring/NetMQMonitor.cs
index 30d74d26d..7b05f3354 100644
--- a/src/NetMQ/Monitoring/NetMQMonitor.cs
+++ b/src/NetMQ/Monitoring/NetMQMonitor.cs
@@ -68,84 +68,48 @@ public NetMQMonitor(NetMQSocket socket, string endpoint, bool ownsSocket = false
m_ownsMonitoringSocket = ownsSocket;
}
- ///
- /// The monitoring address.
- ///
+ ///
public string Endpoint { get; }
- ///
- /// Get whether this monitor is currently running.
- ///
- ///
- /// Start the monitor running via either or .
- /// Stop the monitor via either or .
- ///
+ ///
public bool IsRunning { get; private set; }
- ///
- /// Gets and sets the timeout interval for poll iterations when using and .
- ///
- ///
- /// The higher the number the longer it may take the to stop the monitor.
- /// This value has no effect when the monitor is run via .
- ///
+ ///
public TimeSpan Timeout { get; set; }
#region Events
- ///
- /// Raised whenever any monitored event fires.
- ///
+ ///
public event EventHandler? EventReceived;
- ///
- /// Occurs when a connection is made to a socket.
- ///
+ ///
public event EventHandler? Connected;
- ///
- /// Occurs when a synchronous connection attempt failed, and its completion is being polled for.
- ///
+ ///
public event EventHandler? ConnectDelayed;
- ///
- /// Occurs when an asynchronous connect / reconnection attempt is being handled by a reconnect timer.
- ///
+ ///
public event EventHandler? ConnectRetried;
- ///
- /// Occurs when a socket is bound to an address and is ready to accept connections.
- ///
+ ///
public event EventHandler? Listening;
- ///
- /// Occurs when a socket could not bind to an address.
- ///
+ ///
public event EventHandler? BindFailed;
- ///
- /// Occurs when a connection from a remote peer has been established with a socket's listen address.
- ///
+ ///
public event EventHandler? Accepted;
- ///
- /// Occurs when a connection attempt to a socket's bound address fails.
- ///
+ ///
public event EventHandler? AcceptFailed;
- ///
- /// Occurs when a connection was closed.
- ///
+ ///
public event EventHandler? Closed;
- ///
- /// Occurs when a connection couldn't be closed.
- ///
+ ///
public event EventHandler? CloseFailed;
- ///
- /// Occurs when the stream engine (TCP and IPC specific) detects a corrupted / broken session.
- ///
+ ///
public event EventHandler? Disconnected;
#endregion
@@ -219,13 +183,7 @@ private void InternalClose()
}
}
- ///
- /// Add the monitor object to a NetMQPoller, register to to be signalled on new events
- ///
- ///
- ///
- ///
- ///
+ ///
public void AttachToPoller(T poller) where T : INetMQPoller
{
if (poller == null)
@@ -239,9 +197,7 @@ public void AttachToPoller(T poller) where T : INetMQPoller
poller.Add(m_monitoringSocket);
}
- ///
- /// Remove the monitor object from attached poller
- ///
+ ///
public void DetachFromPoller()
{
DetachFromPoller(false);
@@ -260,10 +216,7 @@ private void DetachFromPoller(bool dispose)
InternalClose();
}
- ///
- /// Start monitor the socket, the method doesn't start a new thread and will block until the monitor poll is stopped
- ///
- /// The Monitor must not have already started nor attached to a poller.
+ ///
public void Start()
{
if (IsRunning)
@@ -287,10 +240,7 @@ public void Start()
}
}
- ///
- /// Start a background task for the monitoring operation.
- ///
- ///
+ ///
public Task StartAsync()
{
if (IsRunning)
@@ -302,10 +252,7 @@ public Task StartAsync()
return Task.Factory.StartNew(Start);
}
- ///
- /// Stop monitoring. Blocks until monitoring completed.
- ///
- /// If this monitor is attached to a poller you must detach it first and not use the stop method.
+ ///
public void Stop()
{
if (m_attachedPoller != null)
From fbb789f4c01a68987400605148d070b9aa80203b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 04:11:04 +0000
Subject: [PATCH 7/8] Improve INetMQMonitor documentation to describe the
abstraction, use inheritdoc in NetMQMonitor
Co-authored-by: drewnoakes <350947+drewnoakes@users.noreply.github.com>
---
src/NetMQ/Monitoring/INetMQMonitor.cs | 9 ++++++++-
src/NetMQ/Monitoring/NetMQMonitor.cs | 11 +----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/NetMQ/Monitoring/INetMQMonitor.cs b/src/NetMQ/Monitoring/INetMQMonitor.cs
index f84be436b..efd8b296f 100644
--- a/src/NetMQ/Monitoring/INetMQMonitor.cs
+++ b/src/NetMQ/Monitoring/INetMQMonitor.cs
@@ -4,8 +4,15 @@
namespace NetMQ.Monitoring
{
///
- /// NetMQMonitor interface, implement to fake the NetMQMonitor in tests.
+ /// Monitors a for events, raising them via events.
///
+ ///
+ /// To run a monitor instance, either:
+ ///
+ /// - Call (blocking) and , or
+ /// - Call and .
+ ///
+ ///
public interface INetMQMonitor : IDisposable
{
///
diff --git a/src/NetMQ/Monitoring/NetMQMonitor.cs b/src/NetMQ/Monitoring/NetMQMonitor.cs
index 7b05f3354..7cb201916 100644
--- a/src/NetMQ/Monitoring/NetMQMonitor.cs
+++ b/src/NetMQ/Monitoring/NetMQMonitor.cs
@@ -7,16 +7,7 @@
namespace NetMQ.Monitoring
{
- ///
- /// Monitors a for events, raising them via events.
- ///
- ///
- /// To run a monitor instance, either:
- ///
- /// - Call (blocking) and , or
- /// - Call and .
- ///
- ///
+ ///
public class NetMQMonitor : INetMQMonitor
{
private readonly NetMQSocket m_monitoringSocket;
From 88dac6c39c011cbb83b9620192dcf09e6f547931 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 6 Oct 2025 04:47:26 +0000
Subject: [PATCH 8/8] Delete NuGet.Config file as it's no longer needed
Co-authored-by: drewnoakes <350947+drewnoakes@users.noreply.github.com>
---
NuGet.Config | 6 ------
1 file changed, 6 deletions(-)
delete mode 100644 NuGet.Config
diff --git a/NuGet.Config b/NuGet.Config
deleted file mode 100644
index 041e71acb..000000000
--- a/NuGet.Config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file