From 3bd15ade939143032fcf7f612d4ef732c2552818 Mon Sep 17 00:00:00 2001 From: Andy Heap Date: Tue, 23 Sep 2025 14:14:45 +0100 Subject: [PATCH] Fix for new handshake and unit test. (#866) Fix for a handshake unit test that was failing once the version was increased to 6.0. This was not actually a failing test but an error in the test itself. On the second protocol entry in sent by the 'server' it supplied a version instead of a range. This meant that under certain circumstances the test would pass, which just so happened to be the case with the current versions when the handshake was added. --- .../Connector/BoltHandshakerTests.cs | 44 ++++++++++++++++--- .../Internal/Connector/BoltHandshaker.cs | 6 ++- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/Neo4j.Driver/Neo4j.Driver.Tests/Connector/BoltHandshakerTests.cs b/Neo4j.Driver/Neo4j.Driver.Tests/Connector/BoltHandshakerTests.cs index 9f0a055de..007cbc30c 100644 --- a/Neo4j.Driver/Neo4j.Driver.Tests/Connector/BoltHandshakerTests.cs +++ b/Neo4j.Driver/Neo4j.Driver.Tests/Connector/BoltHandshakerTests.cs @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -81,16 +82,15 @@ private async Task DoHandshakeAsyncShouldReturnBoltVersion(byte[] streamData, in [Fact] private async Task DoHandshakeAsyncShouldSelectBoltVersionInRange() - { + { var minorVersionPlus = (byte)(BoltProtocolVersion.LatestVersion.MinorVersion + 3); var majorVersion = (byte)BoltProtocolVersion.LatestVersion.MajorVersion; var inputData = new byte[] { 0x00, 0x00, 0x01, 0xFF, //Identifies this as a modern negotiation with manifest v1 0x02, //2 versions to follow - 0x00, 0x04, 0x04, 0x04, - 0x00, majorVersion, - minorVersionPlus, majorVersion, //set to higher than actually supported + 0x00, 0x04, 0x04, 0x04, //4.4 -> 4.0 (range 4) + 0x00, minorVersionPlus, minorVersionPlus, majorVersion, //set to higher than actually supported. latest version + 3 minors -> latest version first major release (e.g. 6.3 -> 6.0 where 6.0 is the current highest supported version). 0x00, //no capability flags set }; @@ -109,6 +109,40 @@ private async Task DoHandshakeAsyncShouldSelectBoltVersionInRange() boltProtocolVersion.Should().Be(new BoltProtocolVersion(BoltProtocolVersion.LatestVersion.MajorVersion, BoltProtocolVersion.LatestVersion.MinorVersion)); } + + [Fact] + public async Task DoHandShakeAsyncShouldThrowIfRangeIsTooLarge() + { + //Range should not be more than the supplied minor version. This would mean that the driver will try + //to select a -ve minor versioned protocol version. + var majorVersion = (byte)BoltProtocolVersion.LatestVersion.MajorVersion; + var minorVersion = (byte)BoltProtocolVersion.LatestVersion.MinorVersion; + var range = (byte)(BoltProtocolVersion.LatestVersion.MinorVersion + 3); //Set the range to be too large + + var inputData = new byte[] + { + 0x00, 0x00, 0x01, 0xFF, //Identifies this as a modern negotiation with manifest v1 + 0x01, //1 versions to follow + 0x00, range, minorVersion, majorVersion, + 0x00, //no capability flags set + }; + + var readerStream = new MemoryStream(inputData); + var socket = new Mock(); + var writerStream = new MemoryStream(); + + socket.SetupGet(x => x.WriterStream).Returns(writerStream); + socket.SetupGet(x => x.ReaderStream).Returns(readerStream); + + var exception = await Record.ExceptionAsync( + () => BoltHandshaker.Default.DoHandshakeAsync( + socket.Object, + new Mock().Object, + CancellationToken.None)) + .ConfigureAwait(false); + + exception.Should().BeOfType(); + } [Fact] public async Task DoHandshakeAsyncShouldThrowIfNotCorrectLengthResult() @@ -142,7 +176,7 @@ public async Task DoHandshakeAsyncShouldThrowIfNotCorrectLengthResult() [InlineData( new byte[] { - 0x00, 0x00, 0x02, 0xFF, //Identifies this as a modern negotiation with manifest v2 + 0x00, 0x00, 0x01, 0xFF, //Identifies this as a modern negotiation with manifest v1 0x00 //0 versions to follow - ERROR })] private async Task DoHandshakeAsyncShouldThrowProtocolException( diff --git a/Neo4j.Driver/Neo4j.Driver/Internal/Connector/BoltHandshaker.cs b/Neo4j.Driver/Neo4j.Driver/Internal/Connector/BoltHandshaker.cs index 06a1f7723..c5ec626b9 100644 --- a/Neo4j.Driver/Neo4j.Driver/Internal/Connector/BoltHandshaker.cs +++ b/Neo4j.Driver/Neo4j.Driver/Internal/Connector/BoltHandshaker.cs @@ -132,6 +132,7 @@ private static async Task> ParseSupportedProtocolVersi var lowestVersion = new BoltProtocolVersion(protocolVersionAndRange.version.MajorVersion, protocolVersionAndRange.version.MinorVersion - protocolVersionAndRange.range); + //If the protocol version from the server is one that this driver knows about add it to the list. foreach (var protocol in BoltProtocolFactory.SupportedVersions) { if (protocol >= lowestVersion && protocol <= protocolVersionAndRange.version) @@ -155,8 +156,9 @@ private static async Task ParseCapabilityBitmask( private static BoltProtocolVersion SelectProtocolVersion(List protocolVersions) { - //We iterate through the versions supplied by the server in the manifest and select the newest one (highest version number) - return protocolVersions.Max(); + //We now select the highest version that is in the list. This list contains the set of versions that both + //the server and the driver know about. + return protocolVersions.Max(); } private static async Task EncodeAndSendHandshakeResponseAsync(