This is an automated email from the ASF dual-hosted git repository.

blankensteiner pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-dotpulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new cc33381  Add partition router tests and update xunit packages (#214)
cc33381 is described below

commit cc33381550616ff4b5f72f5fa7d6ed2095a99721
Author: entvex <[email protected]>
AuthorDate: Wed Apr 17 14:59:52 2024 +0200

    Add partition router tests and update xunit packages (#214)
    
    Added unit tests for the SinglePartitionRouter and 
RoundRobinPartitionRouter classes. These tests check that chosen partitions 
return non-negative integers. Also, minor adjustments have been made to the 
implementation. The xUnit package versions in the project file have been 
updated for the latest features and bug fixes.
    
    Co-authored-by: David Jensen <[email protected]>
---
 CHANGELOG.md                                       |  6 ++++
 src/DotPulsar/RoundRobinPartitionRouter.cs         |  8 ++---
 src/DotPulsar/SinglePartitionRouter.cs             |  2 +-
 tests/DotPulsar.Tests/DotPulsar.Tests.csproj       |  4 +--
 .../Internal/RoundRobinPartitionRouterTests.cs     | 37 ++++++++++++++++++++++
 .../Internal/SinglePartitionRouterTests.cs         | 37 ++++++++++++++++++++++
 6 files changed, 87 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b96886..8761c97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this 
file.
 
 The format is based on [Keep a 
Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to 
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [Unreleased]
+
+### Fixed
+
+- RoundRobinPartitionRouter and SinglePartitionRouter could return a negative 
number. They have been changed to ensure they always return a non-negative 
integer.
+
 ## [3.2.0] - 2024-04-09
 
 ### Added
diff --git a/src/DotPulsar/RoundRobinPartitionRouter.cs 
b/src/DotPulsar/RoundRobinPartitionRouter.cs
index 68a0512..bf692e1 100644
--- a/src/DotPulsar/RoundRobinPartitionRouter.cs
+++ b/src/DotPulsar/RoundRobinPartitionRouter.cs
@@ -18,7 +18,7 @@ using DotPulsar.Abstractions;
 using HashDepot;
 
 /// <summary>
-/// The round robin partition messages router, which is the default router.
+/// The round-robin partition messages router, which is the default router.
 /// If a key is provided, the producer will hash the key and publish the 
message to a particular partition.
 /// If a key is not provided, the producer will publish messages across all 
partitions in a round-robin fashion to achieve maximum throughput.
 /// </summary>
@@ -27,7 +27,7 @@ public sealed class RoundRobinPartitionRouter : IMessageRouter
     private int _partitionIndex;
 
     /// <summary>
-    /// Initializes a new instance of the round robin partition router
+    /// Initializes a new instance of the round-robin partition router
     /// </summary>
     public RoundRobinPartitionRouter()
     {
@@ -35,13 +35,13 @@ public sealed class RoundRobinPartitionRouter : 
IMessageRouter
     }
 
     /// <summary>
-    /// Choose a partition in round robin routing mode
+    /// Choose a partition in round-robin routing mode
     /// </summary>
     public int ChoosePartition(MessageMetadata messageMetadata, int 
numberOfPartitions)
     {
         var keyBytes = messageMetadata.KeyBytes;
         if (keyBytes is not null && keyBytes.Length > 0)
-            return (int) MurmurHash3.Hash32(keyBytes, 0) % numberOfPartitions;
+            return (int) (MurmurHash3.Hash32(keyBytes, 0) % 
numberOfPartitions);
 
         return Interlocked.Increment(ref _partitionIndex) % numberOfPartitions;
     }
diff --git a/src/DotPulsar/SinglePartitionRouter.cs 
b/src/DotPulsar/SinglePartitionRouter.cs
index 6425bad..c4284c6 100644
--- a/src/DotPulsar/SinglePartitionRouter.cs
+++ b/src/DotPulsar/SinglePartitionRouter.cs
@@ -49,7 +49,7 @@ public sealed class SinglePartitionRouter : IMessageRouter
     {
         var keyBytes = messageMetadata.KeyBytes;
         if (keyBytes is not null && keyBytes.Length > 0)
-            return (int) MurmurHash3.Hash32(keyBytes, 0) % numberOfPartitions;
+            return (int) (MurmurHash3.Hash32(keyBytes, 0) % 
numberOfPartitions);
 
         if (_partitionIndex == -1)
             _partitionIndex = new Random().Next(0, numberOfPartitions);
diff --git a/tests/DotPulsar.Tests/DotPulsar.Tests.csproj 
b/tests/DotPulsar.Tests/DotPulsar.Tests.csproj
index 4bc2f44..edc8c2b 100644
--- a/tests/DotPulsar.Tests/DotPulsar.Tests.csproj
+++ b/tests/DotPulsar.Tests/DotPulsar.Tests.csproj
@@ -26,8 +26,8 @@
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
     <PackageReference Include="Testcontainers" Version="3.8.0" />
     <PackageReference Include="ToxiproxyNetCore" Version="1.0.35" />
-    <PackageReference Include="xunit" Version="2.7.0" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
+    <PackageReference Include="xunit" Version="2.7.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.8">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; 
buildtransitive</IncludeAssets>
     </PackageReference>
diff --git a/tests/DotPulsar.Tests/Internal/RoundRobinPartitionRouterTests.cs 
b/tests/DotPulsar.Tests/Internal/RoundRobinPartitionRouterTests.cs
new file mode 100644
index 0000000..681cae0
--- /dev/null
+++ b/tests/DotPulsar.Tests/Internal/RoundRobinPartitionRouterTests.cs
@@ -0,0 +1,37 @@
+namespace DotPulsar.Tests.Internal;
+
+public class RoundRobinPartitionRouterTests
+{
+    [Fact]
+    public void ChoosePartition_GivenBytes_ShouldReturnNonNegativeInteger()
+    {
+        // Arrange
+        var router = new RoundRobinPartitionRouter();
+        var messageMetadata = new MessageMetadata
+        {
+            KeyBytes = [13, 144, 79, 245] //-179335155
+        };
+
+        //Act
+        var result = router.ChoosePartition(messageMetadata, 4);
+
+        //Assert
+        result.Should().BeInRange(0, 3);
+    }
+
+    [Theory]
+    [InlineData(1)]
+    [InlineData(int.MaxValue)]
+    public void 
ChoosePartition_GivenNoMetadata_ShouldReturnNonNegativeInteger(int 
numberOfPartitions)
+    {
+        // Arrange
+        var router = new RoundRobinPartitionRouter();
+        var messageMetadata = new MessageMetadata();
+
+        //Act
+        var result = router.ChoosePartition(messageMetadata, 
numberOfPartitions);
+
+        //Assert
+        result.Should().BeInRange(0, numberOfPartitions);
+    }
+}
diff --git a/tests/DotPulsar.Tests/Internal/SinglePartitionRouterTests.cs 
b/tests/DotPulsar.Tests/Internal/SinglePartitionRouterTests.cs
new file mode 100644
index 0000000..0a86ce1
--- /dev/null
+++ b/tests/DotPulsar.Tests/Internal/SinglePartitionRouterTests.cs
@@ -0,0 +1,37 @@
+namespace DotPulsar.Tests.Internal;
+
+public class SinglePartitionRouterTests
+{
+    [Fact]
+    public void ChoosePartition_GivenBytes_ShouldReturnNonNegativeInteger()
+    {
+        // Arrange
+        var router = new SinglePartitionRouter();
+        var messageMetadata = new MessageMetadata
+        {
+            KeyBytes = [13, 144, 79, 245] //-179335155
+        };
+
+        //Act
+        var result = router.ChoosePartition(messageMetadata, 4);
+
+        //Assert
+        result.Should().BeInRange(0, 3);
+    }
+
+    [Theory]
+    [InlineData(1)]
+    [InlineData(int.MaxValue)]
+    public void 
ChoosePartition_GivenNoMetadata_ShouldReturnNonNegativeInteger(int 
numberOfPartitions)
+    {
+        // Arrange
+        var router = new SinglePartitionRouter();
+        var messageMetadata = new MessageMetadata();
+
+        //Act
+        var result = router.ChoosePartition(messageMetadata, 
numberOfPartitions);
+
+        //Assert
+        result.Should().BeInRange(0, numberOfPartitions);
+    }
+}

Reply via email to