From 5236bb87b3f862a6a5d52e662ab5db792215954f Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Tue, 13 Dec 2022 16:11:15 +0000 Subject: [PATCH 1/2] Move sourcegen testing from Roslyn4.0 to Roslyn4.4. --- src/libraries/System.Text.Json/System.Text.Json.sln | 6 +++--- ...csproj => System.Text.Json.TestLibrary.Roslyn4.4.csproj} | 2 +- ...ystem.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj} | 6 +++--- ....Text.Json.SourceGeneration.Roslyn4.4.Unit.Tests.csproj} | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) rename src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/{System.Text.Json.TestLibrary.Roslyn4.0.csproj => System.Text.Json.TestLibrary.Roslyn4.4.csproj} (77%) rename src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/{System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj => System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj} (64%) rename src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/{System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj => System.Text.Json.SourceGeneration.Roslyn4.4.Unit.Tests.csproj} (69%) diff --git a/src/libraries/System.Text.Json/System.Text.Json.sln b/src/libraries/System.Text.Json/System.Text.Json.sln index 948f9d3d8d8b7a..46935b79af4c25 100644 --- a/src/libraries/System.Text.Json/System.Text.Json.sln +++ b/src/libraries/System.Text.Json/System.Text.Json.sln @@ -47,15 +47,15 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "System.Text.Json.FSharp.Tes EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.TestLibrary.Roslyn3.11", "tests\System.Text.Json.SourceGeneration.TestLibrary\System.Text.Json.TestLibrary.Roslyn3.11.csproj", "{5C0CE30B-DD4A-4F7A-87C0-5243F0C86885}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.TestLibrary.Roslyn4.0", "tests\System.Text.Json.SourceGeneration.TestLibrary\System.Text.Json.TestLibrary.Roslyn4.0.csproj", "{FCA21178-0411-45D6-B597-B7BE145CEE33}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.TestLibrary.Roslyn4.4", "tests\System.Text.Json.SourceGeneration.TestLibrary\System.Text.Json.TestLibrary.Roslyn4.4.csproj", "{FCA21178-0411-45D6-B597-B7BE145CEE33}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn3.11.Tests", "tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj", "{66AD4B7E-CF15-4A8F-8BF8-7E1BC6176D07}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn4.0.Tests", "tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj", "{33599A6C-F340-4E1B-9B4D-CB8946C22140}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn4.4.Tests", "tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj", "{33599A6C-F340-4E1B-9B4D-CB8946C22140}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests", "tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests.csproj", "{256A4653-4287-44B3-BDEF-67FC1522ED2F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests", "tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj", "{F6A18EB5-A8CC-4A39-9E85-5FA226019C3D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn4.4.Unit.Tests", "tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn4.4.Unit.Tests.csproj", "{F6A18EB5-A8CC-4A39-9E85-5FA226019C3D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.Tests", "tests\System.Text.Json.Tests\System.Text.Json.Tests.csproj", "{A0178BAA-A1AF-4C69-8E4A-A700A2723DDC}" EndProject diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.0.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.4.csproj similarity index 77% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.0.csproj rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.4.csproj index 138741ea7741a8..d3e8eae7ffa98c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.0.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.4.csproj @@ -3,6 +3,6 @@ - + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj similarity index 64% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj index 588f7863f3116a..ec457d5630e7ce 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj @@ -2,13 +2,13 @@ - + - - + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Unit.Tests.csproj similarity index 69% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Unit.Tests.csproj index 672ec185379977..17222dfd27484c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Unit.Tests.csproj @@ -1,7 +1,7 @@ - $(MicrosoftCodeAnalysisVersion_4_0) - $(DefineConstants);ROSLYN4_0_OR_GREATER + $(MicrosoftCodeAnalysisVersion_4_4) + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER true @@ -12,6 +12,6 @@ - + From fe3a6270757967cd1cd9000f2b49adf0ae85e082 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Thu, 22 Dec 2022 16:07:42 +0000 Subject: [PATCH 2/2] Create a minimal reproduction for the wasm failure. --- .../System/Text/Json/Document/JsonDocument.cs | 36 ++---- .../Serialization/WasmReproTest.cs | 59 +++++++++ ...m.Text.Json.SourceGeneration.Tests.targets | 100 +------------- .../JsonDocumentTests.cs | 122 +++++++++--------- .../JsonElementCloneTests.cs | 52 ++++---- 5 files changed, 155 insertions(+), 214 deletions(-) create mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/WasmReproTest.cs diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs index 9042a31b9d07e5..9e24a27800064a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs @@ -21,7 +21,7 @@ namespace System.Text.Json /// public sealed partial class JsonDocument : IDisposable { - private ReadOnlyMemory _utf8Json; + private readonly ReadOnlyMemory _utf8Json; private MetadataDb _parsedData; private byte[]? _extraRentedArrayPoolBytes; @@ -41,7 +41,11 @@ private JsonDocument( PooledByteBufferWriter? extraPooledByteBufferWriter = null, bool isDisposable = true) { - Debug.Assert(!utf8Json.IsEmpty); + if (utf8Json.IsEmpty) + { + // replaces debug assertion with runtime check. + throw new ArgumentException(); + } // Both rented values better be null if we're not disposable. Debug.Assert(isDisposable || @@ -60,32 +64,7 @@ private JsonDocument( /// public void Dispose() { - int length = _utf8Json.Length; - if (length == 0 || !IsDisposable) - { - return; - } - - _parsedData.Dispose(); - _utf8Json = ReadOnlyMemory.Empty; - - if (_extraRentedArrayPoolBytes != null) - { - byte[]? extraRentedBytes = Interlocked.Exchange(ref _extraRentedArrayPoolBytes, null); - - if (extraRentedBytes != null) - { - // When "extra rented bytes exist" it contains the document, - // and thus needs to be cleared before being returned. - extraRentedBytes.AsSpan(0, length).Clear(); - ArrayPool.Shared.Return(extraRentedBytes); - } - } - else if (_extraPooledByteBufferWriter != null) - { - PooledByteBufferWriter? extraBufferWriter = Interlocked.Exchange(ref _extraPooledByteBufferWriter, null); - extraBufferWriter?.Dispose(); - } + // Make no-op, disables clearing of the _utf8Json buffer } /// @@ -1059,6 +1038,7 @@ private static void Parse( private void CheckNotDisposed() { + // Given the other changes in this class, this should never be true. if (_utf8Json.IsEmpty) { ThrowHelper.ThrowObjectDisposedException_JsonDocument(); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/WasmReproTest.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/WasmReproTest.cs new file mode 100644 index 00000000000000..679a862dbb49fd --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/WasmReproTest.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; +using System.Text.Json.Serialization; +using Xunit; + +namespace System.Text.Json.SourceGeneration.Tests +{ + public sealed class WasmReproTest + { + [Fact] + public static void TestFailingOnWasmOnly() + { + // Failing test adapted from ReferenceHandlerTests.ReadTestClassesWithExtensionOption + + var options = new JsonSerializerOptions + { + ReferenceHandler = ReferenceHandler.Preserve + }; + + string json = GetLargeJsonObject(); + + // First five calls succeed without issue + for (int i = 0; i < 5; i++) + { + object value = JsonSerializer.Deserialize(json, options); + Assert.IsType(value); + } + + // Fails on wasm release: + // System.ObjectDisposedException : Cannot access a disposed object. + // Object name: 'JsonDocument'. + // at System.Text.Json.ThrowHelper.ThrowObjectDisposedException_JsonDocument() + // at System.Text.Json.JsonDocument.CheckNotDisposed() + // at System.Text.Json.JsonDocument.TextEquals(Int32 index, ReadOnlySpan`1 otherUtf8Text, Boolean isPropertyName, Boolean shouldUnescape) + // at System.Text.Json.JsonElement.TextEqualsHelper(ReadOnlySpan`1 utf8Text, Boolean isPropertyName, Boolean shouldUnescape) + // at System.Text.Json.JsonProperty.EscapedNameEquals(ReadOnlySpan`1 utf8Text) + // at System.Text.Json.JsonSerializer.TryHandleReferenceFromJsonElement(Utf8JsonReader& reader, ReadStack& state, JsonElement element, Object& referenceValue) + // at System.Text.Json.Serialization.Converters.ObjectConverter.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, Rea + JsonSerializer.Deserialize(json, options); + } + + private static string GetLargeJsonObject() + { + var sb = new StringBuilder(); + sb.Append('{'); + + for (int i = 0; i < 200; i++) + { + sb.Append($@"""Key{i}"":{i},"); + } + + sb.Length -= 1; + sb.Append('}'); + return sb.ToString(); + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets index 1b9e0d17b199e8..c2956e15d93270 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets @@ -14,106 +14,8 @@ $(DefineConstants);BUILDING_SOURCE_GENERATOR_TESTS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonDocumentTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonDocumentTests.cs index 9bae2532b760c8..7e2a209b541ec4 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonDocumentTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonDocumentTests.cs @@ -1723,67 +1723,67 @@ public static void ReadArrayWithComments() } } - [Fact] - public static void CheckUseAfterDispose() - { - var buffer = new ArrayBufferWriter(1024); - using (JsonDocument doc = JsonDocument.Parse("{\"First\":1}", default)) - { - JsonElement root = doc.RootElement; - JsonProperty property = root.EnumerateObject().First(); - doc.Dispose(); - - Assert.Throws(() => root.ValueKind); - Assert.Throws(() => root.GetArrayLength()); - Assert.Throws(() => root.EnumerateArray()); - Assert.Throws(() => root.EnumerateObject()); - Assert.Throws(() => root.GetDouble()); - Assert.Throws(() => root.TryGetDouble(out double _)); - Assert.Throws(() => root.GetSByte()); - Assert.Throws(() => root.TryGetSByte(out sbyte _)); - Assert.Throws(() => root.GetByte()); - Assert.Throws(() => root.TryGetByte(out byte _)); - Assert.Throws(() => root.GetInt16()); - Assert.Throws(() => root.TryGetInt16(out short _)); - Assert.Throws(() => root.GetUInt16()); - Assert.Throws(() => root.TryGetUInt16(out ushort _)); - Assert.Throws(() => root.GetInt32()); - Assert.Throws(() => root.TryGetInt32(out int _)); - Assert.Throws(() => root.GetUInt32()); - Assert.Throws(() => root.TryGetUInt32(out uint _)); - Assert.Throws(() => root.GetInt64()); - Assert.Throws(() => root.TryGetInt64(out long _)); - Assert.Throws(() => root.GetUInt64()); - Assert.Throws(() => root.TryGetUInt64(out ulong _)); - Assert.Throws(() => root.GetString()); - const string ThrowsAnyway = "throws-anyway"; - Assert.Throws(() => root.ValueEquals(ThrowsAnyway)); - Assert.Throws(() => root.ValueEquals(ThrowsAnyway.AsSpan())); - Assert.Throws(() => root.ValueEquals(Encoding.UTF8.GetBytes(ThrowsAnyway))); - Assert.Throws(() => root.GetBytesFromBase64()); - Assert.Throws(() => root.TryGetBytesFromBase64(out byte[] _)); - Assert.Throws(() => root.GetBoolean()); - Assert.Throws(() => root.GetRawText()); - - Assert.Throws(() => - { - using var writer = new Utf8JsonWriter(buffer); - root.WriteTo(writer); - }); - - Assert.Throws(() => - { - using var writer = new Utf8JsonWriter(buffer); - doc.WriteTo(writer); - }); - - Assert.Throws(() => - { - using var writer = new Utf8JsonWriter(buffer); - property.WriteTo(writer); - }); - } - } + //[Fact] + //public static void CheckUseAfterDispose() + //{ + // var buffer = new ArrayBufferWriter(1024); + // using (JsonDocument doc = JsonDocument.Parse("{\"First\":1}", default)) + // { + // JsonElement root = doc.RootElement; + // JsonProperty property = root.EnumerateObject().First(); + // doc.Dispose(); + + // Assert.Throws(() => root.ValueKind); + // Assert.Throws(() => root.GetArrayLength()); + // Assert.Throws(() => root.EnumerateArray()); + // Assert.Throws(() => root.EnumerateObject()); + // Assert.Throws(() => root.GetDouble()); + // Assert.Throws(() => root.TryGetDouble(out double _)); + // Assert.Throws(() => root.GetSByte()); + // Assert.Throws(() => root.TryGetSByte(out sbyte _)); + // Assert.Throws(() => root.GetByte()); + // Assert.Throws(() => root.TryGetByte(out byte _)); + // Assert.Throws(() => root.GetInt16()); + // Assert.Throws(() => root.TryGetInt16(out short _)); + // Assert.Throws(() => root.GetUInt16()); + // Assert.Throws(() => root.TryGetUInt16(out ushort _)); + // Assert.Throws(() => root.GetInt32()); + // Assert.Throws(() => root.TryGetInt32(out int _)); + // Assert.Throws(() => root.GetUInt32()); + // Assert.Throws(() => root.TryGetUInt32(out uint _)); + // Assert.Throws(() => root.GetInt64()); + // Assert.Throws(() => root.TryGetInt64(out long _)); + // Assert.Throws(() => root.GetUInt64()); + // Assert.Throws(() => root.TryGetUInt64(out ulong _)); + // Assert.Throws(() => root.GetString()); + // const string ThrowsAnyway = "throws-anyway"; + // Assert.Throws(() => root.ValueEquals(ThrowsAnyway)); + // Assert.Throws(() => root.ValueEquals(ThrowsAnyway.AsSpan())); + // Assert.Throws(() => root.ValueEquals(Encoding.UTF8.GetBytes(ThrowsAnyway))); + // Assert.Throws(() => root.GetBytesFromBase64()); + // Assert.Throws(() => root.TryGetBytesFromBase64(out byte[] _)); + // Assert.Throws(() => root.GetBoolean()); + // Assert.Throws(() => root.GetRawText()); + + // Assert.Throws(() => + // { + // using var writer = new Utf8JsonWriter(buffer); + // root.WriteTo(writer); + // }); + + // Assert.Throws(() => + // { + // using var writer = new Utf8JsonWriter(buffer); + // doc.WriteTo(writer); + // }); + + // Assert.Throws(() => + // { + // using var writer = new Utf8JsonWriter(buffer); + // property.WriteTo(writer); + // }); + // } + //} [Fact] public static void CheckUseDefault() diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonElementCloneTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonElementCloneTests.cs index fe0822e31fed03..7e707fcd4b43af 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonElementCloneTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonElementCloneTests.cs @@ -8,32 +8,32 @@ namespace System.Text.Json.Tests { public static class JsonElementCloneTests { - [Fact] - public static void CloneTwiceFromSameDocument() - { - string json = "[[]]"; - JsonElement root; - JsonElement clone; - JsonElement clone2; - - using (JsonDocument doc = JsonDocument.Parse(json)) - { - root = doc.RootElement; - clone = root.Clone(); - clone2 = root.Clone(); - - Assert.Equal(json, clone.GetRawText()); - Assert.NotSame(doc, clone.SniffDocument()); - Assert.NotSame(doc, clone2.SniffDocument()); - } - - // After document Dispose - Assert.Equal(json, clone.GetRawText()); - Assert.Equal(json, clone2.GetRawText()); - Assert.NotSame(clone.SniffDocument(), clone2.SniffDocument()); - - Assert.Throws(() => root.GetRawText()); - } + //[Fact] + //public static void CloneTwiceFromSameDocument() + //{ + // string json = "[[]]"; + // JsonElement root; + // JsonElement clone; + // JsonElement clone2; + + // using (JsonDocument doc = JsonDocument.Parse(json)) + // { + // root = doc.RootElement; + // clone = root.Clone(); + // clone2 = root.Clone(); + + // Assert.Equal(json, clone.GetRawText()); + // Assert.NotSame(doc, clone.SniffDocument()); + // Assert.NotSame(doc, clone2.SniffDocument()); + // } + + // // After document Dispose + // Assert.Equal(json, clone.GetRawText()); + // Assert.Equal(json, clone2.GetRawText()); + // Assert.NotSame(clone.SniffDocument(), clone2.SniffDocument()); + + // Assert.Throws(() => root.GetRawText()); + //} [Fact] public static void CloneInnerElementFromClonedElement()