Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/MongoDB.Bson/ObjectModel/BsonDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ public BsonDocument(BsonElement element)
Add(element);
}

/// <summary>
/// Initializes a new instance of the BsonDocument by coping elements from another BsonDocument.
/// </summary>
/// <param name="document">The document whose elements will be copied</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public BsonDocument(BsonDocument document)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

_allowDuplicateNames = document.AllowDuplicateNames;
AddRange(document);
}

/// <summary>
/// Initializes a new instance of the BsonDocument class and adds new elements from a dictionary of key/value pairs.
/// </summary>
Expand Down Expand Up @@ -733,7 +749,7 @@ public virtual void Clear()
/// <returns>A shallow clone of the document.</returns>
public override BsonValue Clone()
{
BsonDocument clone = new BsonDocument();
BsonDocument clone = new BsonDocument() { AllowDuplicateNames = AllowDuplicateNames };
foreach (BsonElement element in _elements)
{
clone.Add(element.Clone());
Expand All @@ -745,7 +761,7 @@ public override BsonValue Clone()
/// Compares this document to another document.
/// </summary>
/// <param name="rhs">The other document.</param>
/// <returns>A 32-bit signed integer that indicates whether this document is less than, equal to, or greather than the other.</returns>
/// <returns>A 32-bit signed integer that indicates whether this document is less than, equal to, or greater than the other.</returns>
public virtual int CompareTo(BsonDocument rhs)
{
if (rhs == null) { return 1; }
Expand Down Expand Up @@ -776,7 +792,7 @@ public virtual int CompareTo(BsonDocument rhs)
/// Compares the BsonDocument to another BsonValue.
/// </summary>
/// <param name="other">The other BsonValue.</param>
/// <returns>A 32-bit signed integer that indicates whether this BsonDocument is less than, equal to, or greather than the other BsonValue.</returns>
/// <returns>A 32-bit signed integer that indicates whether this BsonDocument is less than, equal to, or greater than the other BsonValue.</returns>
public override int CompareTo(BsonValue other)
{
if (other == null) { return 1; }
Expand Down Expand Up @@ -818,7 +834,7 @@ public virtual bool ContainsValue(BsonValue value)
/// <returns>A deep clone of the document.</returns>
public override BsonValue DeepClone()
{
BsonDocument clone = new BsonDocument();
BsonDocument clone = new BsonDocument() { AllowDuplicateNames = AllowDuplicateNames };
foreach (BsonElement element in _elements)
{
clone.Add(element.DeepClone());
Expand Down
60 changes: 60 additions & 0 deletions tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,21 @@ public void TestClone()
var clone = (BsonDocument)document.Clone();
Assert.Equal(clone, document);
Assert.Same(clone["d"], document["d"]);
Assert.False(clone.AllowDuplicateNames);
}

[Fact]
public void TestClone_with_duplicate_elements()
{
var document = new BsonDocument(allowDuplicateNames: true)
{
{ "d", new BsonDocument("x", 1) },
{ "d", new BsonDocument("x", 2) },
};

var clone = (BsonDocument)document.Clone();
clone.Should().Be(document);
clone.AllowDuplicateNames.Should().BeTrue();
}

[Fact]
Expand All @@ -153,6 +168,7 @@ public void TestConstructorElement()
{
var element = new BsonElement("x", 1);
var document = new BsonDocument(element);
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand All @@ -168,6 +184,7 @@ public void TestConstructorElements()
new BsonElement("y", 2)
};
var document = new BsonDocument((IEnumerable<BsonElement>)elements);
Assert.False(document.AllowDuplicateNames);
Assert.Equal(2, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(2, document["y"].AsInt32);
Expand All @@ -184,6 +201,7 @@ public void TestConstructorElementsDocument()
{
var originalDocument = new BsonDocument { { "x", 1 }, { "y", 2 } };
var document = new BsonDocument(originalDocument);
Assert.False(document.AllowDuplicateNames);
Assert.Equal(2, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(2, document["y"].AsInt32);
Expand All @@ -195,6 +213,20 @@ public void TestConstructorElementsDocument()
Assert.Same(originalDocument.GetElement("y").Value, document.GetElement("y").Value);
}

[Fact]
public void TestConstructorElementsDocumentDuplicateNames()
{
var documentA = new BsonDocument(allowDuplicateNames: true)
{
{ "x", 1 },
{ "x", 2 },
};
var documentB = new BsonDocument(documentA);

documentB.AllowDuplicateNames.Should().BeTrue();
documentB.Elements.ShouldAllBeEquivalentTo(documentA.Elements);
}

[Fact]
public void TestConstructorElementsParams()
{
Expand All @@ -203,6 +235,8 @@ public void TestConstructorElementsParams()
#pragma warning disable 618
var document = new BsonDocument(element1, element2);
#pragma warning restore
Assert.False(document.AllowDuplicateNames);
Assert.Equal(2, document.ElementCount);
Assert.Equal(2, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(2, document["y"].AsInt32);
Expand All @@ -219,6 +253,7 @@ public void TestConstructorDictionaryGeneric()
{
var dictionary = new Dictionary<string, object> { { "x", 1 } };
var document = new BsonDocument(dictionary);
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand All @@ -233,6 +268,7 @@ public void TestConstructorDictionaryGenericWithKeys()
#pragma warning disable 618
var document = new BsonDocument(dictionary, keys);
#pragma warning restore
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand All @@ -244,6 +280,7 @@ public void TestConstructorIDictionary()
{
var hashtable = (IDictionary)new Hashtable { { "x", 1 } };
var document = new BsonDocument(hashtable);
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand All @@ -255,6 +292,7 @@ public void TestConstructorIDictionaryGeneric()
{
var dictionary = (IDictionary<string, object>)new Dictionary<string, object> { { "x", 1 } };
var document = new BsonDocument(dictionary);
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand All @@ -269,6 +307,7 @@ public void TestConstructorIDictionaryGenericWithKeys()
#pragma warning disable 618
var document = new BsonDocument(dictionary, keys);
#pragma warning restore
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand All @@ -283,6 +322,7 @@ public void TestConstructorIDictionaryWithKeys()
#pragma warning disable 618
var document = new BsonDocument(hashtable, keys);
#pragma warning restore
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand All @@ -293,6 +333,7 @@ public void TestConstructorIDictionaryWithKeys()
public void TestConstructorNameValue()
{
var document = new BsonDocument("x", 1);
Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
Expand Down Expand Up @@ -374,6 +415,25 @@ public void TestDeepClone()
var clone = (BsonDocument)document.DeepClone();
Assert.Equal(clone, document);
Assert.NotSame(clone["d"], document["d"]);
Assert.False(((BsonDocument)document["d"]).AllowDuplicateNames);
}

[Fact]
public void TestDeepClone_with_duplicate_elements()
{
var documentWithDuplicateElements = new BsonDocument(allowDuplicateNames: true)
{
{ "x", 1 },
{ "x", 2 }
};

var document = new BsonDocument("d", documentWithDuplicateElements);
var clone = (BsonDocument)document.DeepClone();
var clonedNestedDocument = (BsonDocument)clone["d"];

clonedNestedDocument.Should().NotBeSameAs((BsonDocument)document["d"]);
clonedNestedDocument.Elements.ShouldAllBeEquivalentTo(documentWithDuplicateElements.Elements);
clonedNestedDocument.AllowDuplicateNames.Should().BeTrue();
}

[Fact]
Expand Down