From ab1d04e32a4d932205b2ffa3dd384282fb8e64be Mon Sep 17 00:00:00 2001 From: Maryam Ariyan Date: Mon, 3 Jun 2019 17:21:10 -0700 Subject: [PATCH] Adds JsonElement.ValueEquals / JsonProperty.NameEquals APIs, (dotnet/corefx#37911) * - Rename Utf8JsonReader.TextEquals to Utf8JsonReader.ValueTextEquals - Implement JsonElement.ValueEquals and add code coverage - Reuse logic for JsonProperty and add code coverage - improve header documentation - cleanup tests Commit migrated from https://github.com/dotnet/corefx/commit/f09135a373caa94eca1566f7ad497aaf19587140 --- .../System.Text.Json/ref/System.Text.Json.cs | 11 +- .../src/System/Text/Json/Document/JsonDocument.cs | 83 +++++++ .../src/System/Text/Json/Document/JsonElement.cs | 101 +++++++++ .../src/System/Text/Json/Document/JsonProperty.cs | 62 ++++++ .../src/System/Text/Json/Reader/Utf8JsonReader.cs | 39 +++- .../System.Text.Json/tests/JsonDocumentTests.cs | 247 ++++++++++++++++++++- .../tests/System.Text.Json.Tests.csproj | 2 +- .../tests/TestClasses.ClassWithComplexObjects.cs | 1 + ...s.cs => Utf8JsonReaderTests.ValueTextEquals.cs} | 129 +++++++---- .../System.Text.Json/tests/Utf8JsonReaderTests.cs | 7 +- 10 files changed, 628 insertions(+), 54 deletions(-) rename src/libraries/System.Text.Json/tests/{Utf8JsonReaderTests.TextEquals.cs => Utf8JsonReaderTests.ValueTextEquals.cs} (77%) diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index ebda0cb..bb0457a 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -73,6 +73,9 @@ namespace System.Text.Json public bool TryGetUInt32(out uint value) { throw null; } [System.CLSCompliantAttribute(false)] public bool TryGetUInt64(out ulong value) { throw null; } + public bool ValueEquals(System.ReadOnlySpan utf8Text) { throw null; } + public bool ValueEquals(System.ReadOnlySpan text) { throw null; } + public bool ValueEquals(string text) { throw null; } public void WriteAsProperty(System.ReadOnlySpan utf8PropertyName, System.Text.Json.Utf8JsonWriter writer) { } public void WriteAsProperty(System.ReadOnlySpan propertyName, System.Text.Json.Utf8JsonWriter writer) { } public void WriteAsProperty(string propertyName, System.Text.Json.Utf8JsonWriter writer) { } @@ -131,6 +134,9 @@ namespace System.Text.Json private readonly object _dummy; public string Name { get { throw null; } } public System.Text.Json.JsonElement Value { get { throw null; } } + public bool NameEquals(System.ReadOnlySpan utf8Text) { throw null; } + public bool NameEquals(System.ReadOnlySpan text) { throw null; } + public bool NameEquals(string text) { throw null; } public override string ToString() { throw null; } } public partial struct JsonReaderOptions @@ -215,8 +221,6 @@ namespace System.Text.Json public ulong GetUInt64() { throw null; } public bool Read() { throw null; } public void Skip() { } - public bool TextEquals(System.ReadOnlySpan otherUtf8Text) { throw null; } - public bool TextEquals(System.ReadOnlySpan otherText) { throw null; } public bool TryGetBytesFromBase64(out byte[] value) { throw null; } public bool TryGetDateTime(out System.DateTime value) { throw null; } public bool TryGetDateTimeOffset(out System.DateTimeOffset value) { throw null; } @@ -231,6 +235,9 @@ namespace System.Text.Json [System.CLSCompliantAttribute(false)] public bool TryGetUInt64(out ulong value) { throw null; } public bool TrySkip() { throw null; } + public bool ValueTextEquals(System.ReadOnlySpan utf8Text) { throw null; } + public bool ValueTextEquals(System.ReadOnlySpan text) { throw null; } + public bool ValueTextEquals(string text) { throw null; } } public sealed partial class Utf8JsonWriter : System.IDisposable { 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 b5ffa48..528a55e 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 @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Buffers; using System.Buffers.Text; using System.Diagnostics; @@ -257,6 +258,88 @@ namespace System.Text.Json return lastString; } + internal bool TextEquals(int index, ReadOnlySpan otherText, bool isPropertyName) + { + CheckNotDisposed(); + + int matchIndex = isPropertyName ? index - DbRow.Size : index; + + (int lastIdx, string lastString) = _lastIndexAndString; + + if (lastIdx == matchIndex) + { + return otherText.SequenceEqual(lastString.AsSpan()); + } + + byte[] otherUtf8TextArray = null; + + int length = checked(otherText.Length * JsonConstants.MaxExpansionFactorWhileTranscoding); + Span otherUtf8Text = length <= JsonConstants.StackallocThreshold ? + stackalloc byte[length] : + (otherUtf8TextArray = ArrayPool.Shared.Rent(length)); + + ReadOnlySpan utf16Text = MemoryMarshal.AsBytes(otherText); + OperationStatus status = JsonWriterHelper.ToUtf8(utf16Text, otherUtf8Text, out int consumed, out int written); + Debug.Assert(status != OperationStatus.DestinationTooSmall); + if (status > OperationStatus.DestinationTooSmall) // Equivalent to: (status == NeedMoreData || status == InvalidData) + { + return false; + } + Debug.Assert(status == OperationStatus.Done); + Debug.Assert(consumed == utf16Text.Length); + + bool result = TextEquals(index, otherUtf8Text.Slice(0, written), isPropertyName); + + if (otherUtf8TextArray != null) + { + otherUtf8Text.Slice(0, written).Clear(); + ArrayPool.Shared.Return(otherUtf8TextArray); + } + + return result; + } + + internal bool TextEquals(int index, ReadOnlySpan otherUtf8Text, bool isPropertyName) + { + CheckNotDisposed(); + + int matchIndex = isPropertyName ? index - DbRow.Size : index; + + DbRow row = _parsedData.Get(matchIndex); + + CheckExpectedType( + isPropertyName? JsonTokenType.PropertyName : JsonTokenType.String, + row.TokenType); + + ReadOnlySpan data = _utf8Json.Span; + ReadOnlySpan segment = data.Slice(row.Location, row.SizeOrLength); + + if (otherUtf8Text.Length > segment.Length) + { + return false; + } + + if (row.HasComplexChildren) + { + if (otherUtf8Text.Length < segment.Length / JsonConstants.MaxExpansionFactorWhileEscaping) + { + return false; + } + + int idx = segment.IndexOf(JsonConstants.BackSlash); + Debug.Assert(idx != -1); + + if (!otherUtf8Text.StartsWith(segment.Slice(0, idx))) + { + return false; + } + + return JsonReaderHelper.UnescapeAndCompare(segment.Slice(idx), otherUtf8Text.Slice(idx)); + } + + return segment.SequenceEqual(otherUtf8Text); + } + internal string GetNameOfPropertyValue(int index) { // The property name is one row before the property value diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs index e9d12eb..895c467 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs @@ -2,9 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Buffers; using System.Buffers.Text; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.InteropServices; namespace System.Text.Json { @@ -973,6 +976,104 @@ namespace System.Text.Json } /// + /// Compares to the string value of this element. + /// + /// The text to compare against. + /// + /// if the string value of this element matches , + /// otherwise. + /// + /// + /// This value's is not . + /// + /// + /// This method is functionally equal to doing an ordinal comparison of and + /// the result of calling , but avoids creating the string instance. + /// + public bool ValueEquals(string text) + { + // CheckValidInstance is done in the helper + + if (TokenType == JsonTokenType.Null) + { + return text == null; + } + + return TextEqualsHelper(text.AsSpan(), isPropertyName: false); + } + + /// + /// Compares the text represented by to the string value of this element. + /// + /// The UTF-8 encoded text to compare against. + /// + /// if the string value of this element has the same UTF-8 encoding as + /// , otherwise. + /// + /// + /// This value's is not . + /// + /// + /// This method is functionally equal to doing an ordinal comparison of the string produced by UTF-8 decoding + /// with the result of calling , but avoids creating the + /// string instances. + /// + public bool ValueEquals(ReadOnlySpan utf8Text) + { + // CheckValidInstance is done in the helper + + if (TokenType == JsonTokenType.Null) + { + // This is different than Length == 0, in that it tests true for null, but false for "" + return utf8Text == default; + } + + return TextEqualsHelper(utf8Text, isPropertyName: false); + } + + /// + /// Compares to the string value of this element. + /// + /// The text to compare against. + /// + /// if the string value of this element matches , + /// otherwise. + /// + /// + /// This value's is not . + /// + /// + /// This method is functionally equal to doing an ordinal comparison of and + /// the result of calling , but avoids creating the string instance. + /// + public bool ValueEquals(ReadOnlySpan text) + { + // CheckValidInstance is done in the helper + + if (TokenType == JsonTokenType.Null) + { + // This is different than Length == 0, in that it tests true for null, but false for "" + return text == default; + } + + return TextEqualsHelper(text, isPropertyName: false); + } + + internal bool TextEqualsHelper(ReadOnlySpan utf8Text, bool isPropertyName) + { + CheckValidInstance(); + + return _parent.TextEquals(_idx, utf8Text, isPropertyName); + } + + internal bool TextEqualsHelper(ReadOnlySpan text, bool isPropertyName) + { + CheckValidInstance(); + + return _parent.TextEquals(_idx, text, isPropertyName); + } + + /// /// Write the element into the provided writer as a named object property. /// /// The name for this value within the JSON object. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs index 04ada6d5..41900da 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; + namespace System.Text.Json { /// @@ -25,6 +27,66 @@ namespace System.Text.Json public string Name => Value.GetPropertyName(); /// + /// Compares to the name of this property. + /// + /// The text to compare against. + /// + /// if the name of this property matches , + /// otherwise. + /// + /// + /// This value's is not . + /// + /// + /// This method is functionally equal to doing an ordinal comparison of and + /// , but can avoid creating the string instance. + /// + public bool NameEquals(string text) + { + return NameEquals(text.AsSpan()); + } + + /// + /// Compares the text represented by to the name of this property. + /// + /// The UTF-8 encoded text to compare against. + /// + /// if the name of this property has the same UTF-8 encoding as + /// , otherwise. + /// + /// + /// This value's is not . + /// + /// + /// This method is functionally equal to doing an ordinal comparison of and + /// , but can avoid creating the string instance. + /// + public bool NameEquals(ReadOnlySpan utf8Text) + { + return Value.TextEqualsHelper(utf8Text, isPropertyName: true); + } + + /// + /// Compares to the name of this property. + /// + /// The text to compare against. + /// + /// if the name of this property matches , + /// otherwise. + /// + /// + /// This value's is not . + /// + /// + /// This method is functionally equal to doing an ordinal comparison of and + /// , but can avoid creating the string instance. + /// + public bool NameEquals(ReadOnlySpan text) + { + return Value.TextEqualsHelper(text, isPropertyName: true); + } + + /// /// Provides a representation of the property for /// debugging purposes. /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs index e88c980..a5874c9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs @@ -392,7 +392,7 @@ namespace System.Text.Json /// /// Compares the UTF-8 encoded text to the unescaped JSON token value in the source and returns true if they match. /// - /// The UTF-8 encoded text to compare against. + /// The UTF-8 encoded text to compare against. /// True if the JSON token value in the source matches the UTF-8 encoded look up text. /// /// Thrown if trying to find a text match on a JSON token that is not a string @@ -407,13 +407,36 @@ namespace System.Text.Json /// The comparison of the JSON token value in the source and the look up text is done by first unescaping the JSON value in source, /// if required. The look up text is matched as is, without any modifications to it. /// - public bool TextEquals(ReadOnlySpan otherUtf8Text) + public bool ValueTextEquals(ReadOnlySpan utf8Text) { if (!IsTokenTypeString(TokenType)) { throw ThrowHelper.GetInvalidOperationException_ExpectedStringComparison(TokenType); } - return TextEqualsHelper(otherUtf8Text); + return TextEqualsHelper(utf8Text); + } + + /// + /// Compares the string text to the unescaped JSON token value in the source and returns true if they match. + /// + /// The text to compare against. + /// True if the JSON token value in the source matches the look up text. + /// + /// Thrown if trying to find a text match on a JSON token that is not a string + /// (i.e. other than or ). + /// + /// + /// + /// If the look up text is invalid UTF-8 text, the method will return false since you cannot have + /// invalid UTF-8 within the JSON payload. + /// + /// + /// The comparison of the JSON token value in the source and the look up text is done by first unescaping the JSON value in source, + /// if required. The look up text is matched as is, without any modifications to it. + /// + public bool ValueTextEquals(string utf8Text) + { + return ValueTextEquals(utf8Text.AsSpan()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -435,7 +458,7 @@ namespace System.Text.Json /// /// Compares the text to the unescaped JSON token value in the source and returns true if they match. /// - /// The text to compare against. + /// The text to compare against. /// True if the JSON token value in the source matches the look up text. /// /// Thrown if trying to find a text match on a JSON token that is not a string @@ -450,14 +473,14 @@ namespace System.Text.Json /// The comparison of the JSON token value in the source and the look up text is done by first unescaping the JSON value in source, /// if required. The look up text is matched as is, without any modifications to it. /// - public bool TextEquals(ReadOnlySpan otherText) + public bool ValueTextEquals(ReadOnlySpan text) { if (!IsTokenTypeString(TokenType)) { throw ThrowHelper.GetInvalidOperationException_ExpectedStringComparison(TokenType); } - if (MatchNotPossible(otherText.Length)) + if (MatchNotPossible(text.Length)) { return false; } @@ -466,9 +489,8 @@ namespace System.Text.Json Span otherUtf8Text; - ReadOnlySpan utf16Text = MemoryMarshal.AsBytes(otherText); + int length = checked(text.Length * JsonConstants.MaxExpansionFactorWhileTranscoding); - int length = checked(utf16Text.Length * JsonConstants.MaxExpansionFactorWhileTranscoding); if (length > JsonConstants.StackallocThreshold) { otherUtf8TextArray = ArrayPool.Shared.Rent(length); @@ -484,6 +506,7 @@ namespace System.Text.Json } } + ReadOnlySpan utf16Text = MemoryMarshal.AsBytes(text); OperationStatus status = JsonWriterHelper.ToUtf8(utf16Text, otherUtf8Text, out int consumed, out int written); Debug.Assert(status != OperationStatus.DestinationTooSmall); if (status > OperationStatus.DestinationTooSmall) // Equivalent to: (status == NeedMoreData || status == InvalidData) diff --git a/src/libraries/System.Text.Json/tests/JsonDocumentTests.cs b/src/libraries/System.Text.Json/tests/JsonDocumentTests.cs index c8d74f3..c6634c1 100644 --- a/src/libraries/System.Text.Json/tests/JsonDocumentTests.cs +++ b/src/libraries/System.Text.Json/tests/JsonDocumentTests.cs @@ -681,6 +681,7 @@ namespace System.Text.Json.Tests string street = address.GetProperty("street").GetString(); string city = address.GetProperty("city").GetString(); double zipCode = address.GetProperty("zip").GetDouble(); + const string ThrowsAnyway = "throws-anyway"; Assert.Equal(30, age); Assert.Equal("John", first); @@ -700,6 +701,9 @@ namespace System.Text.Json.Tests Assert.Throws(() => address.GetProperty("zip").GetString()); Assert.Throws(() => person.GetProperty("phoneNumbers").GetString()); Assert.Throws(() => person.GetString()); + Assert.Throws(() => person.ValueEquals(ThrowsAnyway)); + Assert.Throws(() => person.ValueEquals(ThrowsAnyway.AsSpan())); + Assert.Throws(() => person.ValueEquals(Encoding.UTF8.GetBytes(ThrowsAnyway))); } } @@ -834,6 +838,10 @@ namespace System.Text.Json.Tests } 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[] bytes)); Assert.Throws(() => root.GetDateTime()); @@ -922,6 +930,10 @@ namespace System.Text.Json.Tests } 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.GetDateTime()); Assert.Throws(() => root.GetDateTimeOffset()); @@ -979,6 +991,10 @@ namespace System.Text.Json.Tests Assert.Equal(value, root.GetUInt64()); 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.GetDateTime()); Assert.Throws(() => root.GetDateTimeOffset()); @@ -1036,6 +1052,10 @@ namespace System.Text.Json.Tests Assert.Throws(() => root.GetUInt64()); 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.GetDateTime()); Assert.Throws(() => root.GetDateTimeOffset()); @@ -1225,6 +1245,10 @@ namespace System.Text.Json.Tests Assert.Throws(() => root.GetUInt64()); 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.GetDateTime()); Assert.Throws(() => root.GetDateTimeOffset()); @@ -1293,6 +1317,10 @@ namespace System.Text.Json.Tests Assert.Throws(() => root.GetUInt64()); 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.GetDateTime()); Assert.Throws(() => root.GetDateTimeOffset()); @@ -1345,6 +1373,10 @@ namespace System.Text.Json.Tests 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.GetDateTime()); @@ -1376,6 +1408,10 @@ namespace System.Text.Json.Tests 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()); @@ -1420,6 +1456,10 @@ namespace System.Text.Json.Tests 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.GetDateTime()); @@ -1470,13 +1510,20 @@ namespace System.Text.Json.Tests { // The Arabic ligature Lam-Alef (U+FEFB) (which happens to, as a standalone, mean "no" in English) // is UTF-8 EF BB BB. So let's leave out a BB and put it in quotes. - using (JsonDocument doc = JsonDocument.Parse(new byte[] { 0x22, 0xEF, 0xBB, 0x22 })) + byte[] badUtf8 = new byte[] { 0x22, 0xEF, 0xBB, 0x22 }; + using (JsonDocument doc = JsonDocument.Parse(badUtf8)) { JsonElement root = doc.RootElement; + const string ErrorMessage = "Cannot transcode invalid UTF-8 JSON text to UTF-16 string."; Assert.Equal(JsonValueType.String, root.Type); - Assert.Throws(() => root.GetString()); + AssertExtensions.Throws(() => root.GetString(), ErrorMessage); Assert.Throws(() => root.GetRawText()); + const string DummyString = "dummy-string"; + Assert.False(root.ValueEquals(badUtf8)); + Assert.False(root.ValueEquals(DummyString)); + Assert.False(root.ValueEquals(DummyString.AsSpan())); + Assert.False(root.ValueEquals(Encoding.UTF8.GetBytes(DummyString))); } } @@ -3034,6 +3081,202 @@ namespace System.Text.Json.Tests } } + [Fact] + public static void ValueEquals_Null_TrueForNullFalseForEmpty() + { + using (JsonDocument doc = JsonDocument.Parse(" null ")) + { + JsonElement jElement = doc.RootElement; + Assert.True(jElement.ValueEquals((string)null)); + Assert.True(jElement.ValueEquals(default(ReadOnlySpan))); + Assert.True(jElement.ValueEquals((ReadOnlySpan)null)); + Assert.True(jElement.ValueEquals(default(ReadOnlySpan))); + + Assert.False(jElement.ValueEquals(Array.Empty())); + Assert.False(jElement.ValueEquals("")); + Assert.False(jElement.ValueEquals("".AsSpan())); + } + } + + [Fact] + public static void ValueEquals_EmptyJsonString_True() + { + using (JsonDocument doc = JsonDocument.Parse("\"\"")) + { + JsonElement jElement = doc.RootElement; + Assert.True(jElement.ValueEquals("")); + Assert.True(jElement.ValueEquals("".AsSpan())); + Assert.True(jElement.ValueEquals(default(ReadOnlySpan))); + Assert.True(jElement.ValueEquals(default(ReadOnlySpan))); + Assert.True(jElement.ValueEquals(Array.Empty())); + } + } + + [Fact] + public static void ValueEquals_TestTextEqualsLargeMatch_True() + { + string lookup = new string('a', 320); + string jsonString = "\"" + lookup + "\""; + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + Assert.True(jElement.ValueEquals((string)lookup)); + Assert.True(jElement.ValueEquals((ReadOnlySpan)lookup.AsSpan())); + } + } + + [Theory] + [InlineData("\"conne\\u0063tionId\"", "connectionId")] + [InlineData("\"connectionId\"", "connectionId")] + [InlineData("\"123\"", "123")] + [InlineData("\"My name is \\\"Ahson\\\"\"", "My name is \"Ahson\"")] + public static void ValueEquals_JsonTokenStringType_True(string jsonString, string expected) + { + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + Assert.True(jElement.ValueEquals(expected)); + Assert.True(jElement.ValueEquals(expected.AsSpan())); + byte[] expectedGetBytes = Encoding.UTF8.GetBytes(expected); + Assert.True(jElement.ValueEquals(expectedGetBytes)); + } + } + + [Theory] + [InlineData("\"conne\\u0063tionId\"", "c")] + public static void ValueEquals_DestinationTooSmallComparesEscaping_False(string jsonString, string other) + { + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + Assert.False(jElement.ValueEquals(other)); + Assert.False(jElement.ValueEquals(other.AsSpan())); + byte[] otherGetBytes = Encoding.UTF8.GetBytes(other); + Assert.False(jElement.ValueEquals(otherGetBytes)); + } + } + + [Theory] + [ActiveIssue(38178)] + [InlineData("\"hello\"", new char[1] { (char)0xDC01 })] // low surrogate - invalid + [InlineData("\"hello\"", new char[1] { (char)0xD801 })] // high surrogate - missing pair + public static void InvalidUTF16Search(string jsonString, char[] lookup) + { + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + Assert.False(jElement.ValueEquals(lookup)); + } + } + + [Theory] + [InlineData("\"connectionId\"", "\"conne\\u0063tionId\"")] + [InlineData("\"conne\\u0063tionId\"", "connecxionId")] // intentionally making mismatch after escaped character + [InlineData("\"conne\\u0063tionId\"", "bonnectionId")] // intentionally changing the expected starting character + public static void ValueEquals_JsonTokenStringType_False(string jsonString, string otherText) + { + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + Assert.False(jElement.ValueEquals(otherText)); + Assert.False(jElement.ValueEquals(otherText.AsSpan())); + byte[] expectedGetBytes = Encoding.UTF8.GetBytes(otherText); + Assert.False(jElement.ValueEquals(expectedGetBytes)); + } + } + + [Theory] + [InlineData("{}")] + [InlineData("{\"\" : \"\"}")] + [InlineData("{\"sample\" : \"\"}")] + [InlineData("{\"sample\" : null}")] + [InlineData("{\"sample\" : \"sample-value\"}")] + [InlineData("{\"connectionId\" : \"123\"}")] + public static void ValueEquals_NotString_Throws(string jsonString) + { + const string ErrorMessage = "The requested operation requires an element of type 'String', but the target element has type 'Object'."; + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + const string ThrowsAnyway = "throws-anyway"; + AssertExtensions.Throws(() => jElement.ValueEquals(ThrowsAnyway), ErrorMessage); + AssertExtensions.Throws(() => jElement.ValueEquals(ThrowsAnyway.AsSpan()), ErrorMessage); + AssertExtensions.Throws(() => jElement.ValueEquals(Encoding.UTF8.GetBytes(ThrowsAnyway)), ErrorMessage); + } + } + + [Fact] + public static void NameEquals_GivenPropertyAndValue_TrueForPropertyName() + { + string jsonString = $"{{ \"aPropertyName\" : \"itsValue\" }}"; + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + JsonProperty property = jElement.EnumerateObject().First(); + + string text = "aPropertyName"; + byte[] expectedGetBytes = Encoding.UTF8.GetBytes(text); + Assert.True(property.NameEquals(text)); + Assert.True(property.NameEquals(text.AsSpan())); + Assert.True(property.NameEquals(expectedGetBytes)); + + text = "itsValue"; + expectedGetBytes = Encoding.UTF8.GetBytes(text); + Assert.False(property.NameEquals(text)); + Assert.False(property.NameEquals(text.AsSpan())); + Assert.False(property.NameEquals(expectedGetBytes)); + } + } + + [Theory] + [InlineData("conne\\u0063tionId", "connectionId")] + [InlineData("connectionId", "connectionId")] + [InlineData("123", "123")] + [InlineData("My name is \\\"Ahson\\\"", "My name is \"Ahson\"")] + public static void NameEquals_UseGoodMatches_True(string propertyName, string otherText) + { + string jsonString = $"{{ \"{propertyName}\" : \"itsValue\" }}"; + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + JsonProperty property = jElement.EnumerateObject().First(); + + byte[] expectedGetBytes = Encoding.UTF8.GetBytes(otherText); + Assert.True(property.NameEquals(otherText)); + Assert.True(property.NameEquals(otherText.AsSpan())); + Assert.True(property.NameEquals(expectedGetBytes)); + } + } + + [Fact] + public static void NameEquals_Empty_Throws() + { + const string jsonString = "{\"\" : \"some-value\"}"; + const string ErrorMessage = "The requested operation requires an element of type 'String', but the target element has type 'Object'."; + using (JsonDocument doc = JsonDocument.Parse(jsonString)) + { + JsonElement jElement = doc.RootElement; + const string ThrowsAnyway = "throws-anyway"; + AssertExtensions.Throws(() => jElement.ValueEquals(ThrowsAnyway), ErrorMessage); + AssertExtensions.Throws(() => jElement.ValueEquals(ThrowsAnyway.AsSpan()), ErrorMessage); + AssertExtensions.Throws(() => jElement.ValueEquals(Encoding.UTF8.GetBytes(ThrowsAnyway)), ErrorMessage); + } + } + + [Theory] + [InlineData("hello")] + [InlineData("")] + [InlineData(null)] + public static void NameEquals_InvalidInstance_Throws(string text) + { + const string ErrorMessage = "Operation is not valid due to the current state of the object."; + JsonProperty prop = default; + AssertExtensions.Throws(() => prop.NameEquals(text), ErrorMessage); + AssertExtensions.Throws(() => prop.NameEquals(text.AsSpan()), ErrorMessage); + byte[] expectedGetBytes = text == null ? null : Encoding.UTF8.GetBytes(text); + AssertExtensions.Throws(() => prop.NameEquals(expectedGetBytes), ErrorMessage); + } + private static void BuildSegmentedReader( out Utf8JsonReader reader, ReadOnlyMemory data, diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj index ef1fcf2..5d94215 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -64,8 +64,8 @@ - + diff --git a/src/libraries/System.Text.Json/tests/TestClasses.ClassWithComplexObjects.cs b/src/libraries/System.Text.Json/tests/TestClasses.ClassWithComplexObjects.cs index bc5c013..da8cc66 100644 --- a/src/libraries/System.Text.Json/tests/TestClasses.ClassWithComplexObjects.cs +++ b/src/libraries/System.Text.Json/tests/TestClasses.ClassWithComplexObjects.cs @@ -53,6 +53,7 @@ namespace System.Text.Json.Serialization.Tests Assert.Equal(JsonValueType.Object, jsonObject.Type); JsonProperty property = jsonObject.EnumerateObject().First(); Assert.Equal("NestedArray", property.Name); + Assert.True(property.NameEquals("NestedArray")); ValidateArray(property.Value); void ValidateArray(JsonElement element) diff --git a/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.TextEquals.cs b/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.ValueTextEquals.cs similarity index 77% rename from src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.TextEquals.cs rename to src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.ValueTextEquals.cs index 8d9ce43..ac3de22 100644 --- a/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.TextEquals.cs +++ b/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.ValueTextEquals.cs @@ -31,22 +31,22 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.PropertyName) { - if (json.TextEquals(connectionId) && json.TextEquals("connectionId".AsSpan())) + if (json.ValueTextEquals(connectionId) && json.ValueTextEquals("connectionId".AsSpan())) { foundId = true; } - else if (json.TextEquals(availableTransports) && json.TextEquals("availableTransports".AsSpan())) + else if (json.ValueTextEquals(availableTransports) && json.ValueTextEquals("availableTransports".AsSpan())) { foundTransports = true; } } else if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(value123) && json.TextEquals("123".AsSpan())) + if (json.ValueTextEquals(value123) && json.ValueTextEquals("123".AsSpan())) { foundValue = true; } - else if (json.TextEquals(embeddedQuotes) && json.TextEquals("My name is \"Ahson\"".AsSpan())) + else if (json.ValueTextEquals(embeddedQuotes) && json.ValueTextEquals("My name is \"Ahson\"".AsSpan())) { foundArrayValue = true; } @@ -72,8 +72,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - Assert.Equal(expectedFound, json.TextEquals(default(ReadOnlySpan))); - Assert.Equal(expectedFound, json.TextEquals(default(ReadOnlySpan))); + Assert.Equal(expectedFound, json.ValueTextEquals(default(ReadOnlySpan))); + Assert.Equal(expectedFound, json.ValueTextEquals(default(ReadOnlySpan))); + Assert.Equal(expectedFound, json.ValueTextEquals(default(string))); break; } } @@ -85,8 +86,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - Assert.Equal(expectedFound, json.TextEquals(default(ReadOnlySpan))); - Assert.Equal(expectedFound, json.TextEquals(default(ReadOnlySpan))); + Assert.Equal(expectedFound, json.ValueTextEquals(default(ReadOnlySpan))); + Assert.Equal(expectedFound, json.ValueTextEquals(default(ReadOnlySpan))); + Assert.Equal(expectedFound, json.ValueTextEquals(default(string))); break; } } @@ -115,7 +117,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.PropertyName) { - if (json.TextEquals(lookup) && json.TextEquals(lookUpString.AsSpan())) + if (json.ValueTextEquals(lookup) && + json.ValueTextEquals(lookUpString) && + json.ValueTextEquals(lookUpString.AsSpan())) { found = true; break; @@ -133,7 +137,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.PropertyName) { - if (json.TextEquals(lookup) && json.TextEquals(lookUpString.AsSpan())) + if (json.ValueTextEquals(lookup) && + json.ValueTextEquals(lookUpString) && + json.ValueTextEquals(lookUpString.AsSpan())) { found = true; break; @@ -167,7 +173,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookup) && json.TextEquals(lookUpString.AsSpan())) + if (json.ValueTextEquals(lookup) && + json.ValueTextEquals(lookUpString) && + json.ValueTextEquals(lookUpString.AsSpan())) { found = true; break; @@ -185,7 +193,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookup) && json.TextEquals(lookUpString.AsSpan())) + if (json.ValueTextEquals(lookup) && + json.ValueTextEquals(lookUpString) && + json.ValueTextEquals(lookUpString.AsSpan())) { found = true; break; @@ -226,7 +236,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookupSpan) && json.TextEquals(lookupChars)) + if (json.ValueTextEquals(lookupSpan) && + json.ValueTextEquals(lookupChars) && + json.ValueTextEquals(new string(lookupChars.ToArray()))) { found = true; break; @@ -244,7 +256,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookupSpan) && json.TextEquals(lookupChars)) + if (json.ValueTextEquals(lookupSpan) && + json.ValueTextEquals(lookupChars) && + json.ValueTextEquals(new string(lookupChars.ToArray()))) { found = true; break; @@ -308,7 +322,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookup) || json.TextEquals(lookupChars)) + if (json.ValueTextEquals(lookup) || + json.ValueTextEquals(lookupChars) || + json.ValueTextEquals(new string(lookupChars.ToArray()))) { found = true; break; @@ -326,7 +342,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookup) || json.TextEquals(lookupChars)) + if (json.ValueTextEquals(lookup) || + json.ValueTextEquals(lookupChars) || + json.ValueTextEquals(new string(lookupChars.ToArray()))) { found = true; break; @@ -353,7 +371,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(new byte[] { (byte)'a' }) || json.TextEquals(new char[] { 'a' })) + if (json.ValueTextEquals(new byte[] { (byte)'a' }) || + json.ValueTextEquals(new char[] { 'a' }) || + json.ValueTextEquals("a")) { found = true; break; @@ -371,7 +391,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(new byte[] { (byte)'a' }) || json.TextEquals(new char[] { 'a' })) + if (json.ValueTextEquals(new byte[] { (byte)'a' }) || + json.ValueTextEquals(new char[] { 'a' }) || + json.ValueTextEquals("a")) { found = true; break; @@ -398,7 +420,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(Encoding.UTF8.GetBytes(lookupString)) || json.TextEquals(lookupString.AsSpan())) + if (json.ValueTextEquals(Encoding.UTF8.GetBytes(lookupString)) || + json.ValueTextEquals(lookupString.AsSpan()) || + json.ValueTextEquals(lookupString)) { found = true; break; @@ -416,7 +440,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(Encoding.UTF8.GetBytes(lookupString)) || json.TextEquals(lookupString.AsSpan())) + if (json.ValueTextEquals(Encoding.UTF8.GetBytes(lookupString)) || + json.ValueTextEquals(lookupString.AsSpan()) || + json.ValueTextEquals(lookupString)) { found = true; break; @@ -441,7 +467,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(Encoding.UTF8.GetBytes(lookupString)) || json.TextEquals(lookupString.AsSpan())) + if (json.ValueTextEquals(Encoding.UTF8.GetBytes(lookupString)) || + json.ValueTextEquals(lookupString.AsSpan()) || + json.ValueTextEquals(lookupString)) { found = true; break; @@ -459,7 +487,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(Encoding.UTF8.GetBytes(lookupString)) || json.TextEquals(lookupString.AsSpan())) + if (json.ValueTextEquals(Encoding.UTF8.GetBytes(lookupString)) || + json.ValueTextEquals(lookupString.AsSpan()) || + json.ValueTextEquals(lookupString)) { found = true; break; @@ -484,7 +514,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(Encoding.UTF8.GetBytes(lookupString)) || json.TextEquals(lookupString.AsSpan())) + if (json.ValueTextEquals(Encoding.UTF8.GetBytes(lookupString)) || + json.ValueTextEquals(lookupString.AsSpan()) || + json.ValueTextEquals(lookupString)) { found = true; break; @@ -502,7 +534,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(Encoding.UTF8.GetBytes(lookupString)) || json.TextEquals(lookupString.AsSpan())) + if (json.ValueTextEquals(Encoding.UTF8.GetBytes(lookupString)) || + json.ValueTextEquals(lookupString.AsSpan()) || + json.ValueTextEquals(lookupString)) { found = true; break; @@ -530,7 +564,9 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookup) || json.TextEquals("Hello, \"Ahson\"".AsSpan())) + if (json.ValueTextEquals(lookup) || + json.ValueTextEquals("Hello, \"Ahson\"".AsSpan()) || + json.ValueTextEquals("Hello, \"Ahson\"")) { found = true; break; @@ -542,6 +578,7 @@ namespace System.Text.Json.Tests } [Theory] + [ActiveIssue(38178)] [InlineData("\"hello\"", new char[1] { (char)0xDC01 })] // low surrogate - invalid [InlineData("\"hello\"", new char[1] { (char)0xD801 })] // high surrogate - missing pair public static void InvalidUTF16Search(string jsonString, char[] lookup) @@ -554,7 +591,7 @@ namespace System.Text.Json.Tests { if (json.TokenType == JsonTokenType.String) { - if (json.TextEquals(lookup)) + if (json.ValueTextEquals(lookup)) { found = true; break; @@ -575,7 +612,7 @@ namespace System.Text.Json.Tests var json = new Utf8JsonReader(utf8Data, isFinalBlock: true, state: default); Assert.True(json.Read()); Assert.Equal(JsonTokenType.String, json.TokenType); - Assert.False(json.TextEquals(lookup.AsSpan())); + Assert.False(json.ValueTextEquals(lookup.AsSpan())); } [Fact] @@ -589,7 +626,7 @@ namespace System.Text.Json.Tests var json = new Utf8JsonReader(utf8Data, isFinalBlock: true, state: default); Assert.True(json.Read()); Assert.Equal(JsonTokenType.String, json.TokenType); - Assert.False(json.TextEquals(lookup)); + Assert.False(json.ValueTextEquals(lookup)); } [ConditionalFact(nameof(IsX64))] @@ -610,8 +647,8 @@ namespace System.Text.Json.Tests try { - json.TextEquals(jsonString.AsSpan(1, jsonString.Length - 2)); - Assert.True(false, $"Expected OverflowException was not thrown when calling TextEquals with large lookup string"); + json.ValueTextEquals(jsonString.AsSpan(1, jsonString.Length - 2)); + Assert.True(false, $"Expected OverflowException was not thrown when calling ValueTextEquals with large lookup string"); } catch (OverflowException) { } @@ -628,16 +665,24 @@ namespace System.Text.Json.Tests try { - json.TextEquals(default(ReadOnlySpan)); - Assert.True(false, $"Expected InvalidOperationException was not thrown when calling TextEquals with TokenType = {json.TokenType}"); + json.ValueTextEquals(default(ReadOnlySpan)); + Assert.True(false, $"Expected InvalidOperationException was not thrown when calling ValueTextEquals with TokenType = {json.TokenType}"); } catch (InvalidOperationException) { } try { - json.TextEquals(default(ReadOnlySpan)); - Assert.True(false, $"Expected InvalidOperationException was not thrown when calling TextEquals(char) with TokenType = {json.TokenType}"); + json.ValueTextEquals(default(ReadOnlySpan)); + Assert.True(false, $"Expected InvalidOperationException was not thrown when calling ValueTextEquals(char) with TokenType = {json.TokenType}"); + } + catch (InvalidOperationException) + { } + + try + { + json.ValueTextEquals(default(string)); + Assert.True(false, $"Expected InvalidOperationException was not thrown when calling ValueTextEquals(char) with TokenType = {json.TokenType}"); } catch (InvalidOperationException) { } @@ -646,16 +691,24 @@ namespace System.Text.Json.Tests { try { - json.TextEquals(default(ReadOnlySpan)); - Assert.True(false, $"Expected InvalidOperationException was not thrown when calling TextEquals with TokenType = {json.TokenType}"); + json.ValueTextEquals(default(ReadOnlySpan)); + Assert.True(false, $"Expected InvalidOperationException was not thrown when calling ValueTextEquals with TokenType = {json.TokenType}"); + } + catch (InvalidOperationException) + { } + + try + { + json.ValueTextEquals(default(ReadOnlySpan)); + Assert.True(false, $"Expected InvalidOperationException was not thrown when calling ValueTextEquals(char) with TokenType = {json.TokenType}"); } catch (InvalidOperationException) { } try { - json.TextEquals(default(ReadOnlySpan)); - Assert.True(false, $"Expected InvalidOperationException was not thrown when calling TextEquals(char) with TokenType = {json.TokenType}"); + json.ValueTextEquals(default(string)); + Assert.True(false, $"Expected InvalidOperationException was not thrown when calling ValueTextEquals(char) with TokenType = {json.TokenType}"); } catch (InvalidOperationException) { } diff --git a/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs b/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs index 2526085..7d76c5b 100644 --- a/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs +++ b/src/libraries/System.Text.Json/tests/Utf8JsonReaderTests.cs @@ -38,9 +38,10 @@ namespace System.Text.Json.Tests Assert.False(json.Read()); json = default; - JsonTestHelper.AssertThrows(json, (jsonReader) => jsonReader.TextEquals("".AsSpan())); - JsonTestHelper.AssertThrows(json, (jsonReader) => jsonReader.TextEquals(default(ReadOnlySpan))); - JsonTestHelper.AssertThrows(json, (jsonReader) => jsonReader.TextEquals(default(ReadOnlySpan))); + JsonTestHelper.AssertThrows(json, (jsonReader) => jsonReader.ValueTextEquals("")); + JsonTestHelper.AssertThrows(json, (jsonReader) => jsonReader.ValueTextEquals("".AsSpan())); + JsonTestHelper.AssertThrows(json, (jsonReader) => jsonReader.ValueTextEquals(default(ReadOnlySpan))); + JsonTestHelper.AssertThrows(json, (jsonReader) => jsonReader.ValueTextEquals(default(ReadOnlySpan))); TestGetMethodsOnDefault(); } -- 2.7.4