Skip to content

Commit

Permalink
CSHARP-3241: Zstandard compression key in the code must be kept in sy…
Browse files Browse the repository at this point in the history
…nc with the spec.
  • Loading branch information
DmitryLukyanov authored and JamesKovacs committed Nov 3, 2020
1 parent 90bb172 commit b7362c2
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 12 deletions.
53 changes: 53 additions & 0 deletions src/MongoDB.Driver.Core/Core/Compression/CompressorTypeMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* Copyright 2020–present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System;

namespace MongoDB.Driver.Core.Compression
{
internal static class CompressorTypeMapper
{
public static string ToServerName(CompressorType compressorType)
{
switch (compressorType)
{
case CompressorType.Noop:
return "noop";
case CompressorType.Zlib:
return "zlib";
case CompressorType.Snappy:
return "snappy";
case CompressorType.ZStandard:
return "zstd";
default:
throw new ArgumentOutOfRangeException(nameof(compressorType));
}
}

public static bool TryFromServerName(string serverName, out CompressorType compressorType)
{
compressorType = default;
switch (serverName.ToLowerInvariant())
{
case "noop": compressorType = CompressorType.Noop; break;
case "zlib": compressorType = CompressorType.Zlib; break;
case "snappy": compressorType = CompressorType.Snappy; break;
case "zstd": compressorType = CompressorType.ZStandard; break;
default: return false;
}
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1380,7 +1380,7 @@ public void SaveCompressors(string[] compressorNames)
foreach (var compressor in compressorNames)
{
// NOTE: the 'noop' is also expected by the server
if (!Enum.TryParse(compressor, true, out CompressorType compressorType) || !CompressorSource.IsCompressorSupported(compressorType))
if (!CompressorTypeMapper.TryFromServerName(compressor, out CompressorType compressorType) || !CompressorSource.IsCompressorSupported(compressorType))
{
// Keys that aren't supported by a driver MUST be ignored.
continue;
Expand Down
3 changes: 2 additions & 1 deletion src/MongoDB.Driver.Core/Core/Connections/IsMasterHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver.Core.Authentication;
using MongoDB.Driver.Core.Compression;
using MongoDB.Driver.Core.Configuration;
using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.Core.Servers;
Expand All @@ -37,7 +38,7 @@ internal static BsonDocument AddClientDocumentToCommand(BsonDocument command, Bs

internal static BsonDocument AddCompressorsToCommand(BsonDocument command, IEnumerable<CompressorConfiguration> compressors)
{
var compressorsArray = new BsonArray(compressors.Select(x => x.Type.ToString().ToLowerInvariant()));
var compressorsArray = new BsonArray(compressors.Select(x => CompressorTypeMapper.ToServerName(x.Type)));

return command.Add("compression", compressorsArray);
}
Expand Down
2 changes: 1 addition & 1 deletion src/MongoDB.Driver.Core/Core/Connections/IsMasterResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public IReadOnlyList<CompressorType> Compressions
.AsBsonArray
.Select(x =>
{
return Enum.TryParse<CompressorType>(x.AsString, true, out var compressorType)
return CompressorTypeMapper.TryFromServerName(x.AsString, out var compressorType)
? compressorType
// we can have such a case only due to the server bug
: throw new NotSupportedException($"The unsupported compressor name: '{x}'.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,14 @@ public void When_authSource_is_specified(string connectionString, string authSou
}

[Theory]
[InlineData("mongodb://localhost?compressors=noop", CompressorType.Noop)]
[InlineData("mongodb://localhost?compressors=nooP", CompressorType.Noop)]
[InlineData("mongodb://localhost?compressors=zlib", CompressorType.Zlib)]
[InlineData("mongodb://localhost?compressors=Zlib", CompressorType.Zlib)]
[InlineData("mongodb://localhost?compressors=snappy", CompressorType.Snappy)]
[InlineData("mongodb://localhost?compressors=Snappy", CompressorType.Snappy)]
[InlineData("mongodb://localhost?compressors=zstd", CompressorType.ZStandard)]
[InlineData("mongodb://localhost?compressors=Zstd", CompressorType.ZStandard)]
public void When_compressor_is_specified(string connectionString, CompressorType compressor)
{
var subject = new ConnectionString(connectionString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ public class ConnectionDescriptionTests
"{ ok: 1, version: \"2.6.3\" }"
));

private static readonly IEnumerable<CompressorType> __compressors = new[] { CompressorType.Zlib };
private static readonly IEnumerable<CompressorType> __compressors = new[] { CompressorType.Zlib, CompressorType.ZStandard };

private static readonly ConnectionId __connectionId = new ConnectionId(
new ServerId(new ClusterId(), new DnsEndPoint("localhost", 27017)));

private static readonly IsMasterResult __isMasterResult = new IsMasterResult(BsonDocument.Parse(
"{ ok: 1, maxWriteBatchSize: 10, maxBsonObjectSize: 20, maxMessageSizeBytes: 30, compression: ['zlib'] }"
"{ ok: 1, maxWriteBatchSize: 10, maxBsonObjectSize: 20, maxMessageSizeBytes: 30, compression: ['zlib', 'zstd'] }"
));

private static readonly IsMasterResult __isMasterResultWithoutCompression = new IsMasterResult(BsonDocument.Parse(
Expand All @@ -57,7 +57,7 @@ public void AvailableCompressors_should_return_expected_result()
{
var subject = new ConnectionDescription(__connectionId, __isMasterResult, __buildInfoResult);

subject.AvailableCompressors.Count.Should().Be(1);
subject.AvailableCompressors.Count.Should().Be(2);
subject.AvailableCompressors.Should().Equal(__compressors);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@ public void InitializeConnection_should_throw_an_ArgumentNullException_if_the_co

[Theory]
[ParameterAttributeData]
public void InitializeConnectionA_should_build_the_ConnectionDescription_correctly([Values(false, true)] bool async)
public void InitializeConnectionA_should_build_the_ConnectionDescription_correctly(
[Values("noop", "zlib", "snappy", "zstd")] string compressorType,
[Values(false, true)] bool async)
{
var isMasterReply = MessageHelper.BuildReply<RawBsonDocument>(
RawBsonDocumentHelper.FromJson("{ ok: 1, compression: ['zlib'] }"));
RawBsonDocumentHelper.FromJson($"{{ ok: 1, compression: ['{compressorType}'] }}"));
var buildInfoReply = MessageHelper.BuildReply<RawBsonDocument>(
RawBsonDocumentHelper.FromJson("{ ok: 1, version: \"2.6.3\" }"));
var gleReply = MessageHelper.BuildReply<RawBsonDocument>(
Expand All @@ -188,7 +190,20 @@ public void InitializeConnectionA_should_build_the_ConnectionDescription_correct
result.ServerVersion.Should().Be(new SemanticVersion(2, 6, 3));
result.ConnectionId.ServerValue.Should().Be(10);
result.AvailableCompressors.Count.Should().Be(1);
result.AvailableCompressors.Should().Contain(CompressorType.Zlib);
result.AvailableCompressors.Should().Contain(ToCompressorTypeEnum(compressorType));

CompressorType ToCompressorTypeEnum(string ct)
{
switch (ct)
{
case "noop": return CompressorType.Noop;
case "zlib": return CompressorType.Zlib;
case "snappy": return CompressorType.Snappy;
case "zstd": return CompressorType.ZStandard;
default:
throw new InvalidOperationException($"Unexpected compression {compressorType}.");
}
}
}

private IAuthenticator CreateAuthenticator(string authenticatorType, UsernamePasswordCredential credentials)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public void AddCompressorsToCommand_with_compressors_should_return_expected_resu
new CompressorType[] { },
new [] { CompressorType.Zlib },
new [] { CompressorType.Snappy},
new [] { CompressorType.Zlib, CompressorType.Snappy })]
new [] { CompressorType.Zlib, CompressorType.Snappy },
new [] { CompressorType.ZStandard, CompressorType.Snappy })]
CompressorType[] compressorsParameters)
{
var command = IsMasterHelper.CreateCommand();
Expand All @@ -81,7 +82,7 @@ public void AddCompressorsToCommand_with_compressors_should_return_expected_resu
.ToArray();
var result = IsMasterHelper.AddCompressorsToCommand(command, compressors);

var expectedCompressions = string.Join(",", compressorsParameters.Select(c => $"'{c.ToString().ToLowerInvariant()}'"));
var expectedCompressions = string.Join(",", compressorsParameters.Select(c => $"'{CompressorTypeMapper.ToServerName(c)}'"));
result.Should().Be(BsonDocument.Parse($"{{ isMaster : 1, compression: [{expectedCompressions}] }}"));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ public class IsMasterResultTests
{
[Theory]
[InlineData("{ compression : ['zlib'] }", new[] { CompressorType.Zlib })]
[InlineData("{ compression : ['Zlib'] }", new[] { CompressorType.Zlib })]
[InlineData("{ compression : ['zlib', 'snappy'] }", new[] { CompressorType.Zlib, CompressorType.Snappy })]
[InlineData("{ compression : ['zlib', 'snAppy'] }", new[] { CompressorType.Zlib, CompressorType.Snappy })]
[InlineData("{ compression : ['noop'] }", new[] { CompressorType.Noop })]
[InlineData("{ compression : ['nOop'] }", new[] { CompressorType.Noop })]
[InlineData("{ compression : ['zstd'] }", new[] { CompressorType.ZStandard})]
[InlineData("{ compression : ['zsTd'] }", new[] { CompressorType.ZStandard })]
[InlineData("{ compression : [] }", new CompressorType[0])]
[InlineData("{ }", new CompressorType[0])]
public void Compression_should_parse_document_correctly(string json, CompressorType[] expectedCompression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ private void AssertOptions(ConnectionString connectionString, BsonDocument defin
connectionString.AuthSource.Should().Be(expectedOption.Value.AsString);
break;
case "compressors":
var compressors = new BsonArray(connectionString.Compressors.Select(c => c.Type.ToString().ToLowerInvariant()));
var compressors = new BsonArray(connectionString.Compressors.Select(c => CompressorTypeMapper.ToServerName(c.Type)));
var expectedCompressors = RemoveUnsupportedCompressors(expectedOption.Value.AsBsonArray);
compressors.Should().Be(expectedCompressors);
break;
Expand Down

0 comments on commit b7362c2

Please sign in to comment.