Skip to content

Commit b0b1134

Browse files
committed
CSHARP-2724: Implement specification for handling native UUID types.
1 parent 64cd12b commit b0b1134

File tree

108 files changed

+4829
-837
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+4829
-837
lines changed

build.cake

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ Task("Test")
115115
.Where(name => !name.ToString().Contains("Atlas")),
116116
testProject =>
117117
{
118+
var testWithDefaultGuidRepresentationMode = Environment.GetEnvironmentVariable("TEST_WITH_DEFAULT_GUID_REPRESENTATION_MODE");
119+
if (testWithDefaultGuidRepresentationMode != null)
120+
{
121+
Console.WriteLine($"TEST_WITH_DEFAULT_GUID_REPRESENTATION_MODE={testWithDefaultGuidRepresentationMode}");
122+
}
123+
var testWithDefaultGuidRepresentation = Environment.GetEnvironmentVariable("TEST_WITH_DEFAULT_GUID_REPRESENTATION");
124+
if (testWithDefaultGuidRepresentation != null)
125+
{
126+
Console.WriteLine($"TEST_WITH_DEFAULT_GUID_REPRESENTATION={testWithDefaultGuidRepresentation}");
127+
}
128+
118129
DotNetCoreTest(
119130
testProject.FullPath,
120131
new DotNetCoreTestSettings {
@@ -125,6 +136,49 @@ Task("Test")
125136
}
126137
);
127138
});
139+
140+
// currently we are not running this Task on Evergreen (only locally occassionally)
141+
Task("TestAllGuidRepresentations")
142+
.IsDependentOn("Build")
143+
.DoesForEach(
144+
GetFiles("./**/*.Tests.csproj")
145+
// .Where(name => name.ToString().Contains("Bson.Tests")) // uncomment to only test Bson
146+
.Where(name => !name.ToString().Contains("Atlas")),
147+
testProject =>
148+
{
149+
var modes = new string[][]
150+
{
151+
new[] { "V2", "Unspecified" },
152+
new[] { "V2", "JavaLegacy" },
153+
new[] { "V2", "Standard" },
154+
new[] { "V2", "PythonLegacy" },
155+
new[] { "V2", "CSharpLegacy" },
156+
new[] { "V3", "Unspecified" }
157+
};
158+
159+
foreach (var mode in modes)
160+
{
161+
var testWithGuidRepresentationMode = mode[0];
162+
var testWithGuidRepresentation = mode[1];
163+
Console.WriteLine($"TEST_WITH_DEFAULT_GUID_REPRESENTATION_MODE={testWithGuidRepresentationMode}");
164+
Console.WriteLine($"TEST_WITH_DEFAULT_GUID_REPRESENTATION={testWithGuidRepresentation}");
165+
166+
DotNetCoreTest(
167+
testProject.FullPath,
168+
new DotNetCoreTestSettings {
169+
NoBuild = true,
170+
NoRestore = true,
171+
Configuration = configuration,
172+
ArgumentCustomization = args => args.Append("-- RunConfiguration.TargetPlatform=x64"),
173+
EnvironmentVariables = new Dictionary<string, string>
174+
{
175+
{ "TEST_WITH_DEFAULT_GUID_REPRESENTATION_MODE", testWithGuidRepresentationMode },
176+
{ "TEST_WITH_DEFAULT_GUID_REPRESENTATION", testWithGuidRepresentation }
177+
}
178+
}
179+
);
180+
}
181+
});
128182

129183
Task("TestAtlasConnectivity")
130184
.IsDependentOn("Build")

src/MongoDB.Bson/BsonDefaults.cs

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using System.Collections.Generic;
1718
using System.Dynamic;
1819
using MongoDB.Bson.Serialization;
@@ -27,11 +28,28 @@ public static class BsonDefaults
2728
private static bool __dynamicArraySerializerWasSet;
2829
private static IBsonSerializer __dynamicArraySerializer;
2930
private static bool __dynamicDocumentSerializerWasSet;
30-
private static IBsonSerializer __dynamicDocumentSerializer;
31+
private static IBsonSerializer __dynamicDocumentSerializer;
3132
private static GuidRepresentation __guidRepresentation = GuidRepresentation.CSharpLegacy;
33+
private static GuidRepresentationMode __guidRepresentationMode = GuidRepresentationMode.V2;
3234
private static int __maxDocumentSize = int.MaxValue;
3335
private static int __maxSerializationDepth = 100;
3436

37+
// static constructor
38+
static BsonDefaults()
39+
{
40+
var testWithDefaultGuidRepresentation = Environment.GetEnvironmentVariable("TEST_WITH_DEFAULT_GUID_REPRESENTATION");
41+
if (testWithDefaultGuidRepresentation != null)
42+
{
43+
var _ = Enum.TryParse(testWithDefaultGuidRepresentation, out __guidRepresentation); // ignore errors
44+
}
45+
46+
var testWithDefaultGuidRepresentationMode = Environment.GetEnvironmentVariable("TEST_WITH_DEFAULT_GUID_REPRESENTATION_MODE");
47+
if (testWithDefaultGuidRepresentationMode != null)
48+
{
49+
var _ = Enum.TryParse(testWithDefaultGuidRepresentationMode, out __guidRepresentationMode); // ignore errors
50+
}
51+
}
52+
3553
// public static properties
3654
/// <summary>
3755
/// Gets or sets the dynamic array serializer.
@@ -46,10 +64,10 @@ public static IBsonSerializer DynamicArraySerializer
4664
}
4765
return __dynamicArraySerializer;
4866
}
49-
set
67+
set
5068
{
5169
__dynamicArraySerializerWasSet = true;
52-
__dynamicArraySerializer = value;
70+
__dynamicArraySerializer = value;
5371
}
5472
}
5573

@@ -58,30 +76,64 @@ public static IBsonSerializer DynamicArraySerializer
5876
/// </summary>
5977
public static IBsonSerializer DynamicDocumentSerializer
6078
{
61-
get
79+
get
6280
{
6381
if (!__dynamicDocumentSerializerWasSet)
6482
{
6583
__dynamicDocumentSerializer = BsonSerializer.LookupSerializer<ExpandoObject>();
6684
}
67-
return __dynamicDocumentSerializer;
85+
return __dynamicDocumentSerializer;
6886
}
69-
set
87+
set
7088
{
7189
__dynamicDocumentSerializerWasSet = true;
72-
__dynamicDocumentSerializer = value;
90+
__dynamicDocumentSerializer = value;
7391
}
7492
}
7593

7694
/// <summary>
77-
/// Gets or sets the default representation to be used in serialization of
78-
/// Guids to the database.
79-
/// <seealso cref="MongoDB.Bson.GuidRepresentation"/>
95+
/// Gets or sets the default representation to be used in serialization of
96+
/// Guids to the database.
97+
/// <seealso cref="MongoDB.Bson.GuidRepresentation"/>
8098
/// </summary>
99+
[Obsolete("Configure serializers instead.")]
81100
public static GuidRepresentation GuidRepresentation
82101
{
83-
get { return __guidRepresentation; }
84-
set { __guidRepresentation = value; }
102+
get
103+
{
104+
if (BsonDefaults.GuidRepresentationMode != GuidRepresentationMode.V2)
105+
{
106+
throw new InvalidOperationException("BsonDefaults.GuidRepresentation can only be used when BsonDefaults.GuidRepresentationMode is V2.");
107+
}
108+
return __guidRepresentation;
109+
}
110+
set
111+
{
112+
if (BsonDefaults.GuidRepresentationMode != GuidRepresentationMode.V2)
113+
{
114+
throw new InvalidOperationException("BsonDefaults.GuidRepresentation can only be used when BsonDefaults.GuidRepresentationMode is V2.");
115+
}
116+
__guidRepresentation = value;
117+
}
118+
}
119+
120+
/// <summary>
121+
/// Gets or sets the default representation to be used in serialization of
122+
/// Guids to the database.
123+
/// <seealso cref="MongoDB.Bson.GuidRepresentation"/>
124+
/// </summary>
125+
[Obsolete("This property will be removed in a later release.")]
126+
public static GuidRepresentationMode GuidRepresentationMode
127+
{
128+
get { return __guidRepresentationMode; }
129+
set
130+
{
131+
__guidRepresentationMode = value;
132+
if (value == GuidRepresentationMode.V3)
133+
{
134+
__guidRepresentation = GuidRepresentation.Unspecified;
135+
}
136+
}
85137
}
86138

87139
/// <summary>

src/MongoDB.Bson/IO/BsonBinaryReader.cs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ public class BsonBinaryReader : BsonReader
2727
// private fields
2828
private readonly Stream _baseStream;
2929
private readonly BsonStream _bsonStream;
30-
private readonly BsonBinaryReaderSettings _settings; // same value as in base class just declared as derived class
3130
private BsonBinaryReaderContext _context;
3231

3332
// constructors
@@ -59,7 +58,6 @@ public BsonBinaryReader(Stream stream, BsonBinaryReaderSettings settings)
5958

6059
_baseStream = stream;
6160
_bsonStream = (stream as BsonStream) ?? new BsonStreamAdapter(stream);
62-
_settings = settings; // already frozen by base class
6361

6462
_context = new BsonBinaryReaderContext(null, ContextType.TopLevel, 0, 0);
6563
}
@@ -87,6 +85,14 @@ public BsonStream BsonStream
8785
get { return _bsonStream; }
8886
}
8987

88+
/// <summary>
89+
/// Gets the settings of the writer.
90+
/// </summary>
91+
public new BsonBinaryReaderSettings Settings
92+
{
93+
get { return (BsonBinaryReaderSettings)base.Settings; }
94+
}
95+
9096
// public methods
9197
/// <summary>
9298
/// Closes the reader.
@@ -140,24 +146,33 @@ public override BsonBinaryData ReadBinaryData()
140146
}
141147
size = size2;
142148

143-
if (_settings.FixOldBinarySubTypeOnInput)
149+
if (Settings.FixOldBinarySubTypeOnInput)
144150
{
145151
subType = BsonBinarySubType.Binary; // replace obsolete OldBinary with new Binary sub type
146152
}
147153
}
148154

149155
var bytes = _bsonStream.ReadBytes(size);
150156

151-
GuidRepresentation guidRepresentation;
152-
switch (subType)
157+
BsonBinaryData binaryData;
158+
if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
159+
{
160+
GuidRepresentation guidRepresentation;
161+
switch (subType)
162+
{
163+
case BsonBinarySubType.UuidLegacy: guidRepresentation = Settings.GuidRepresentation; break;
164+
case BsonBinarySubType.UuidStandard: guidRepresentation = GuidRepresentation.Standard; break;
165+
default: guidRepresentation = GuidRepresentation.Unspecified; break;
166+
}
167+
binaryData = new BsonBinaryData(bytes, subType, guidRepresentation);
168+
}
169+
else
153170
{
154-
case BsonBinarySubType.UuidLegacy: guidRepresentation = _settings.GuidRepresentation; break;
155-
case BsonBinarySubType.UuidStandard: guidRepresentation = GuidRepresentation.Standard; break;
156-
default: guidRepresentation = GuidRepresentation.Unspecified; break;
171+
binaryData = new BsonBinaryData(bytes, subType);
157172
}
158173

159174
State = GetNextState();
160-
return new BsonBinaryData(bytes, subType, guidRepresentation);
175+
return binaryData;
161176
}
162177
#pragma warning restore 618
163178

@@ -287,7 +302,7 @@ public override long ReadDateTime()
287302
var value = _bsonStream.ReadInt64();
288303
if (value == BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch + 1)
289304
{
290-
if (_settings.FixOldDateTimeMaxValueOnInput)
305+
if (Settings.FixOldDateTimeMaxValueOnInput)
291306
{
292307
value = BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch;
293308
}
@@ -411,7 +426,7 @@ public override string ReadJavaScript()
411426
if (Disposed) { ThrowObjectDisposedException(); }
412427
VerifyBsonType("ReadJavaScript", BsonType.JavaScript);
413428
State = GetNextState();
414-
return _bsonStream.ReadString(_settings.Encoding);
429+
return _bsonStream.ReadString(Settings.Encoding);
415430
}
416431

417432
/// <summary>
@@ -426,7 +441,7 @@ public override string ReadJavaScriptWithScope()
426441
var startPosition = _bsonStream.Position; // position of size field
427442
var size = ReadSize();
428443
_context = new BsonBinaryReaderContext(_context, ContextType.JavaScriptWithScope, startPosition, size);
429-
var code = _bsonStream.ReadString(_settings.Encoding);
444+
var code = _bsonStream.ReadString(Settings.Encoding);
430445

431446
State = BsonReaderState.ScopeDocument;
432447
return code;
@@ -474,7 +489,7 @@ public override string ReadName(INameDecoder nameDecoder)
474489
ThrowInvalidState("ReadName", BsonReaderState.Name);
475490
}
476491

477-
CurrentName = nameDecoder.Decode(_bsonStream, _settings.Encoding);
492+
CurrentName = nameDecoder.Decode(_bsonStream, Settings.Encoding);
478493
State = BsonReaderState.Value;
479494

480495
if (_context.ContextType == ContextType.Document)
@@ -568,8 +583,8 @@ public override BsonRegularExpression ReadRegularExpression()
568583
if (Disposed) { ThrowObjectDisposedException(); }
569584
VerifyBsonType("ReadRegularExpression", BsonType.RegularExpression);
570585
State = GetNextState();
571-
var pattern = _bsonStream.ReadCString(_settings.Encoding);
572-
var options = _bsonStream.ReadCString(_settings.Encoding);
586+
var pattern = _bsonStream.ReadCString(Settings.Encoding);
587+
var options = _bsonStream.ReadCString(Settings.Encoding);
573588
return new BsonRegularExpression(pattern, options);
574589
}
575590

@@ -611,7 +626,7 @@ public override string ReadString()
611626
if (Disposed) { ThrowObjectDisposedException(); }
612627
VerifyBsonType("ReadString", BsonType.String);
613628
State = GetNextState();
614-
return _bsonStream.ReadString(_settings.Encoding);
629+
return _bsonStream.ReadString(Settings.Encoding);
615630
}
616631

617632
/// <summary>
@@ -623,7 +638,7 @@ public override string ReadSymbol()
623638
if (Disposed) { ThrowObjectDisposedException(); }
624639
VerifyBsonType("ReadSymbol", BsonType.Symbol);
625640
State = GetNextState();
626-
return _bsonStream.ReadString(_settings.Encoding);
641+
return _bsonStream.ReadString(Settings.Encoding);
627642
}
628643

629644
/// <summary>
@@ -814,9 +829,9 @@ private int ReadSize()
814829
var message = string.Format("Size {0} is not valid because it is negative.", size);
815830
throw new FormatException(message);
816831
}
817-
if (size > _settings.MaxDocumentSize)
832+
if (size > Settings.MaxDocumentSize)
818833
{
819-
var message = string.Format("Size {0} is not valid because it is larger than MaxDocumentSize {1}.", size, _settings.MaxDocumentSize);
834+
var message = string.Format("Size {0} is not valid because it is larger than MaxDocumentSize {1}.", size, Settings.MaxDocumentSize);
820835
throw new FormatException(message);
821836
}
822837
return size;

src/MongoDB.Bson/IO/BsonBinaryReaderSettings.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,15 @@ protected override BsonReaderSettings CloneImplementation()
139139
Encoding = _encoding,
140140
FixOldBinarySubTypeOnInput = _fixOldBinarySubTypeOnInput,
141141
FixOldDateTimeMaxValueOnInput = _fixOldDateTimeMaxValueOnInput,
142-
GuidRepresentation = GuidRepresentation,
143142
MaxDocumentSize = _maxDocumentSize
144143
};
144+
#pragma warning disable 618
145+
if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
146+
{
147+
clone.GuidRepresentation = GuidRepresentation;
148+
}
149+
#pragma warning restore 618
150+
145151
return clone;
146152
}
147153
}

0 commit comments

Comments
 (0)