Skip to content

Commit 0d3d6e4

Browse files
committed
CSHARP-2294: Add ErrorLabels property to MongoException.
1 parent ddf6e5c commit 0d3d6e4

File tree

4 files changed

+125
-6
lines changed

4 files changed

+125
-6
lines changed

src/MongoDB.Driver.Core/MongoCommandException.cs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,11 @@
1414
*/
1515

1616
using System;
17-
using System.Collections.Generic;
18-
using System.Linq;
1917
#if NET45
2018
using System.Runtime.Serialization;
2119
#endif
22-
using System.Text;
23-
using System.Threading.Tasks;
2420
using MongoDB.Bson;
25-
using MongoDB.Bson.Serialization;
2621
using MongoDB.Driver.Core.Connections;
27-
using MongoDB.Driver.Core.Misc;
2822

2923
namespace MongoDB.Driver
3024
{
@@ -36,6 +30,27 @@ namespace MongoDB.Driver
3630
#endif
3731
public class MongoCommandException : MongoServerException
3832
{
33+
#region static
34+
private static void AddErrorLabelsFromCommandResult(MongoCommandException exception, BsonDocument result)
35+
{
36+
// note: make a best effort to extract the error labels from the result, but never throw an exception
37+
if (result != null)
38+
{
39+
BsonValue errorLabels;
40+
if (result.TryGetValue("errorLabels", out errorLabels) && errorLabels.IsBsonArray)
41+
{
42+
foreach (var errorLabel in errorLabels.AsBsonArray)
43+
{
44+
if (errorLabel.IsString)
45+
{
46+
exception.AddErrorLabel(errorLabel.AsString);
47+
}
48+
}
49+
}
50+
}
51+
}
52+
#endregion
53+
3954
// fields
4055
private readonly BsonDocument _command;
4156
private readonly BsonDocument _result;
@@ -64,6 +79,8 @@ public MongoCommandException(ConnectionId connectionId, string message, BsonDocu
6479
{
6580
_command = command; // can be null
6681
_result = result; // can be null
82+
83+
AddErrorLabelsFromCommandResult(this, result);
6784
}
6885

6986
#if NET45

src/MongoDB.Driver.Core/MongoException.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
*/
1515

1616
using System;
17+
using System.Collections.Generic;
1718
#if NET45
1819
using System.Runtime.Serialization;
20+
using MongoDB.Driver.Core.Misc;
1921
#endif
2022

2123
namespace MongoDB.Driver
@@ -28,6 +30,9 @@ namespace MongoDB.Driver
2830
#endif
2931
public class MongoException : Exception
3032
{
33+
// private fields
34+
private readonly List<string> _errorLabels = new List<string>();
35+
3136
// constructors
3237
/// <summary>
3338
/// Initializes a new instance of the <see cref="MongoException"/> class.
@@ -57,6 +62,36 @@ public MongoException(string message, Exception innerException)
5762
public MongoException(SerializationInfo info, StreamingContext context)
5863
: base(info, context)
5964
{
65+
_errorLabels = (List<string>)info.GetValue(nameof(_errorLabels), typeof(List<String>));
66+
}
67+
#endif
68+
69+
// public properties
70+
/// <summary>
71+
/// Gets the error labels.
72+
/// </summary>
73+
/// <value>
74+
/// The error labels.
75+
/// </value>
76+
public IReadOnlyList<string> ErrorLabels => _errorLabels;
77+
78+
// public methods
79+
/// <summary>
80+
/// Adds an error label.
81+
/// </summary>
82+
/// <param name="errorLabel">The error label.</param>
83+
public void AddErrorLabel(string errorLabel)
84+
{
85+
Ensure.IsNotNull(errorLabel, nameof(errorLabel));
86+
_errorLabels.Add(errorLabel);
87+
}
88+
89+
#if NET45
90+
/// <inheritdoc/>
91+
public override void GetObjectData(SerializationInfo info, StreamingContext context)
92+
{
93+
base.GetObjectData(info, context);
94+
info.AddValue(nameof(_errorLabels), _errorLabels);
6095
}
6196
#endif
6297
}

tests/MongoDB.Driver.Core.Tests/MongoCommandExceptionTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,27 @@ public void constructor_with_message_command_result_should_initialize_subject()
8080
subject.Result.Should().BeSameAs(_commandResult);
8181
}
8282

83+
[Theory]
84+
[InlineData(null, new string[0])]
85+
[InlineData("{ }", new string[0])]
86+
[InlineData("{ }", new string[0])]
87+
[InlineData("{ errorLabels : \"not an array\" }", new string[0])]
88+
[InlineData("{ errorLabels : [ ] }", new string[0])]
89+
[InlineData("{ errorLabels : [ 1 ] }", new string[0])]
90+
[InlineData("{ errorLabels : [ null ] }", new string[0])]
91+
[InlineData("{ errorLabels : [ \"one\" ] }", new[] { "one" })]
92+
[InlineData("{ errorLabels : [ 1, \"one\" ] }", new[] { "one" })]
93+
[InlineData("{ errorLabels : [ \"one\", 1 ] }", new[] { "one" })]
94+
[InlineData("{ errorLabels : [ \"one\", null, \"two\" ] }", new[] { "one", "two" })]
95+
public void constructor_should_add_error_labels(string jsonResult, string[] expectedErrorLabels)
96+
{
97+
var result = jsonResult == null ? null : BsonDocument.Parse(jsonResult);
98+
99+
var subject = new MongoCommandException(_connectionId, _message, _command, result);
100+
101+
subject.ErrorLabels.Should().Equal(expectedErrorLabels);
102+
}
103+
83104
[Fact]
84105
public void ErrorMessage_get_returns_expected_result()
85106
{
@@ -95,6 +116,7 @@ public void ErrorMessage_get_returns_expected_result()
95116
public void Serialization_should_work()
96117
{
97118
var subject = new MongoCommandException(_connectionId, _message, _command, _commandResult);
119+
subject.AddErrorLabel("one");
98120

99121
var formatter = new BinaryFormatter();
100122
using (var stream = new MemoryStream())
@@ -103,6 +125,7 @@ public void Serialization_should_work()
103125
stream.Position = 0;
104126
var rehydrated = (MongoCommandException)formatter.Deserialize(stream);
105127

128+
rehydrated.ErrorLabels.Should().Equal(subject.ErrorLabels);
106129
rehydrated.ConnectionId.Should().Be(subject.ConnectionId);
107130
rehydrated.Message.Should().Be(_message);
108131
rehydrated.InnerException.Should().BeNull();

tests/MongoDB.Driver.Core.Tests/MongoExceptionTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@
1414
*/
1515

1616
using System;
17+
using System.Collections.Generic;
1718
using System.IO;
19+
using System.Linq;
1820
#if NET45
1921
using System.Runtime.Serialization.Formatters.Binary;
2022
#endif
2123
using FluentAssertions;
24+
using MongoDB.Bson.TestHelpers.XunitExtensions;
2225
using Xunit;
2326

2427
namespace MongoDB.Driver
@@ -35,6 +38,7 @@ public void constructor_should_initialize_subject()
3538

3639
subject.Message.Should().BeSameAs(_message);
3740
subject.InnerException.Should().BeNull();
41+
subject.ErrorLabels.Should().HaveCount(0);
3842
}
3943

4044
[Fact]
@@ -44,13 +48,52 @@ public void constructor_with_innerException_should_initialize_subject()
4448

4549
subject.Message.Should().BeSameAs(_message);
4650
subject.InnerException.Should().BeSameAs(_innerException);
51+
subject.ErrorLabels.Should().HaveCount(0);
52+
}
53+
54+
[Theory]
55+
[InlineData(new object[] { new string[0] })]
56+
[InlineData(new object[] { new[] { "one" } })]
57+
[InlineData(new object[] { new[] { "one", "two" } })]
58+
[InlineData(new object[] { new[] { "one", "two", "three" } })]
59+
public void ErrorLabels_should_return_expected_result(string[] errorLabels)
60+
{
61+
var subject = new MongoException(_message);
62+
foreach (var errorLabel in errorLabels)
63+
{
64+
subject.AddErrorLabel(errorLabel);
65+
}
66+
67+
var result = subject.ErrorLabels;
68+
69+
result.Should().Equal(errorLabels);
70+
}
71+
72+
[Theory]
73+
[ParameterAttributeData]
74+
public void AddErrorLabels_should_have_expected_result(
75+
[Values(0, 1, 2, 3)] int existingCount)
76+
{
77+
var subject = new MongoException(_message);
78+
for (var i = 0; i < existingCount; i++)
79+
{
80+
var errorLabel = $"label{i}";
81+
subject.AddErrorLabel(errorLabel);
82+
}
83+
var existingErrorLabels = new List<string>(subject.ErrorLabels);
84+
var newErrorLabel = "x";
85+
86+
subject.AddErrorLabel(newErrorLabel);
87+
88+
subject.ErrorLabels.Should().Equal(existingErrorLabels.Concat(new[] { newErrorLabel }));
4789
}
4890

4991
#if NET45
5092
[Fact]
5193
public void Serialization_should_work()
5294
{
5395
var subject = new MongoException(_message, _innerException);
96+
subject.AddErrorLabel("one");
5497

5598
var formatter = new BinaryFormatter();
5699
using (var stream = new MemoryStream())
@@ -61,6 +104,7 @@ public void Serialization_should_work()
61104

62105
rehydrated.Message.Should().Be(subject.Message);
63106
rehydrated.InnerException.Message.Should().Be(subject.InnerException.Message); // Exception does not override Equals
107+
rehydrated.ErrorLabels.Should().Equal(subject.ErrorLabels);
64108
}
65109
}
66110
#endif

0 commit comments

Comments
 (0)