/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/ExpressionEvaluator/VisualBasic/Test/ResultProvider/ValueFormatterTests.vb
636 строк
24 KB
Cyrus Najmabadi
Organize VB imports
27 июн 2025, 21:53
27 июн 2025, 21:53
e9c47fd
Код
Авторство
О чём код?
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports Microsoft.CodeAnalysis.ExpressionEvaluator Imports Microsoft.VisualStudio.Debugger.Clr Imports Microsoft.VisualStudio.Debugger.Evaluation Imports Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation Imports Xunit Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests Public Class ValueFormatterTests : Inherits VisualBasicResultProviderTestBase <Fact> Public Sub IntegralPrimitives() ' only testing a couple simple cases here...more tests live in ObjectDisplayTests... Assert.Equal("1", FormatValue(CUShort(1))) Assert.Equal("65535", FormatValue(UShort.MaxValue)) Assert.Equal("1", FormatValue(CInt(1))) Assert.Equal("-1", FormatValue(CInt(-1))) Assert.Equal("&H00", FormatValue(CSByte(0), useHexadecimal:=True)) Assert.Equal("&H01", FormatValue(CSByte(1), useHexadecimal:=True)) Assert.Equal("&HFFFFFFFF", FormatValue(CSByte(-1), useHexadecimal:=True)) Assert.Equal("&H0000000000000000", FormatValue(CULng(0), useHexadecimal:=True)) Assert.Equal("&H0000000000000001", FormatValue(CULng(1), useHexadecimal:=True)) Assert.Equal("&HFFFFFFFFFFFFFFFF", FormatValue(ULong.MaxValue, useHexadecimal:=True)) End Sub <Fact> Public Sub Doubles() Assert.Equal("-1.7976931348623157E+308", FormatValue(Double.MinValue)) Assert.Equal("-1.1", FormatValue(CDbl(-1.1))) Assert.Equal("0", FormatValue(CDbl(0))) Assert.Equal("1.1", FormatValue(CDbl(1.1))) Assert.Equal("1.7976931348623157E+308", FormatValue(Double.MaxValue)) Assert.Equal("-Infinity", FormatValue(Double.NegativeInfinity)) Assert.Equal("Infinity", FormatValue(Double.PositiveInfinity)) Assert.Equal("NaN", FormatValue(Double.NaN)) Assert.Equal("4.94065645841247E-324", FormatValue(Double.Epsilon)) End Sub <Fact> Public Sub Singles() Assert.Equal("-3.40282347E+38", FormatValue(Single.MinValue)) Assert.Equal("-1.1", FormatValue(CSng(-1.1))) Assert.Equal("0", FormatValue(CSng(0))) Assert.Equal("1.1", FormatValue(CSng(1.1))) Assert.Equal("3.40282347E+38", FormatValue(Single.MaxValue)) Assert.Equal("-Infinity", FormatValue(Single.NegativeInfinity)) Assert.Equal("Infinity", FormatValue(Single.PositiveInfinity)) Assert.Equal("NaN", FormatValue(Single.NaN)) Assert.Equal("1.401298E-45", FormatValue(Single.Epsilon)) End Sub <Fact> Public Sub Decimals() Assert.Equal("-79228162514264337593543950335", FormatValue(Decimal.MinValue)) Assert.Equal("-1.1", FormatValue(CDec(-1.1))) Assert.Equal("0", FormatValue(CDec(0))) Assert.Equal("1.1", FormatValue(CDec(1.1))) Assert.Equal("79228162514264337593543950335", FormatValue(Decimal.MaxValue)) End Sub <Fact> Public Sub Booleans() Assert.Equal("True", FormatValue(True)) Assert.Equal("False", FormatValue(False)) End Sub <Fact> Public Sub Chars() ' We'll exhaustively test the first 256 code points (single-byte characters) as well ' as a few double-byte characters. Testing all possible characters takes too long. Dim ch As Char For i = 0 To &HFF ch = ChrW(i) Dim expected As String Dim expectedHex As String = Nothing ' NOTE: The old EE used to just display " " for non-printable characters. ' This has been changed in Roslyn to display the equivalent VB constants ' or the actual numeric code point value (this seems far more useful). Select Case CStr(ch) Case vbNullChar expected = "vbNullChar" Case vbBack expected = "vbBack" Case vbCr expected = "vbCr" Case vbFormFeed expected = "vbFormFeed" Case vbLf expected = "vbLf" Case vbTab expected = "vbTab" Case vbVerticalTab expected = "vbVerticalTab" Case """"c expected = """""""""c" Case Else If ObjectDisplay.IsPrintable(ch) Then expected = """" & ch & """c" Else expected = "ChrW(" & i & ")" expectedHex = "ChrW(&H" & i.ToString("X") & ")" End If End Select Assert.Equal(expected, FormatValue(ch)) Assert.Equal(If(expectedHex, expected), FormatValue(ch, useHexadecimal:=True)) Next For Each ch In {ChrW(&HABCD), ChrW(&HFEEF)} Assert.Equal("""" & ch & """c", FormatValue(ch)) Assert.Equal("""" & ch & """c", FormatValue(ch, useHexadecimal:=True)) Next ch = ChrW(&HFFEF) Assert.Equal("ChrW(65519)", FormatValue(ch)) Assert.Equal("ChrW(&HFFEF)", FormatValue(ch, useHexadecimal:=True)) Assert.Equal("ChrW(65535)", FormatValue(Char.MaxValue)) Assert.Equal("ChrW(&HFFFF)", FormatValue(Char.MaxValue, useHexadecimal:=True)) End Sub <Fact> Public Sub Strings() Assert.Equal("Nothing", FormatNull(Of String)()) Assert.Equal("Nothing", FormatNull(Of String)(useHexadecimal:=True)) ' We'll exhaustively test the first 256 code points (single-byte characters) as well ' as a few multi-byte characters. Testing all possible characters takes too long. Dim ch As Char For i = 0 To &HFF ch = ChrW(i) Dim s As String = "a" & ch Dim expected As String Dim expectedHex As String = Nothing Select Case CStr(ch) Case vbNullChar expected = """a"" & vbNullChar" Case vbTab expected = """a"" & vbTab" Case vbCr expected = """a"" & vbCr" Case vbFormFeed expected = """a"" & vbFormFeed" Case vbLf expected = """a"" & vbLf" Case vbBack expected = """a"" & vbBack" Case vbVerticalTab expected = """a"" & vbVerticalTab" Case """" expected = """a""""""" Case Else If ObjectDisplay.IsPrintable(ch) Then expected = """" & s & """" Else expected = """a"" & ChrW(" & i & ")" expectedHex = """a"" & ChrW(&H" & i.ToString("X") & ")" End If End Select Assert.Equal(expected, FormatValue(s)) Assert.Equal(If(expectedHex, expected), FormatValue(s, useHexadecimal:=True)) Next Assert.Equal("""a"" & vbNullChar & ""b""", FormatValue("a" & vbNullChar & "b")) For Each ch In {ChrW(&HABCD), ChrW(&HFEEF)} Assert.Equal("""" & ch & """", FormatValue(CStr(ch))) Assert.Equal("""" & ch & """", FormatValue(CStr(ch), useHexadecimal:=True)) Next ch = ChrW(&HFFEF) Assert.Equal("ChrW(65519)", FormatValue(ch)) Assert.Equal("ChrW(&HFFEF)", FormatValue(ch, useHexadecimal:=True)) Assert.Equal("ChrW(65535)", FormatValue(CStr(Char.MaxValue))) Assert.Equal("ChrW(&HFFFF)", FormatValue(CStr(Char.MaxValue), useHexadecimal:=True)) Dim multiByte = ChrW(&HD83C) & ChrW(&HDFC8) Assert.Equal("""🏈""", FormatValue(multiByte)) Assert.Equal("""🏈""", FormatValue(multiByte, useHexadecimal:=True)) Assert.Equal("🏈", multiByte) multiByte = ChrW(&HDFC8) & ChrW(&HD83C) Assert.Equal("ChrW(57288) & ChrW(55356)", FormatValue(multiByte)) Assert.Equal("ChrW(&HDFC8) & ChrW(&HD83C)", FormatValue(multiByte, useHexadecimal:=True)) End Sub <Fact> Public Sub Void() ' Something happens but, in practice, we expect the debugger to recognize ' that the value is of type void and turn it into the error string ' "Expression has been evaluated and has no value". Assert.Equal("{System.Void}", FormatValue(Nothing, GetType(Void))) End Sub <Fact> Public Sub InvalidValue_1() Const errorMessage = "An error has occurred." Dim clrValue = CreateDkmClrValue(errorMessage, GetType(String), evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.Error) Assert.Equal(errorMessage, (DirectCast(FormatResult("invalidIdentifier", clrValue), DkmFailedEvaluationResult)).ErrorMessage) End Sub <Fact> Public Sub InvalidValue_2() Const errorMessage = "An error has occurred." Dim clrValue = CreateDkmClrValue(errorMessage, GetType(Integer), evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.Error) Assert.Equal(errorMessage, (DirectCast(FormatResult("invalidIdentifier", clrValue), DkmFailedEvaluationResult)).ErrorMessage) End Sub <Fact> Public Sub NonFlagsEnum() Dim source = " Enum E A = 1 B = 2 End Enum " Dim assembly = GetAssembly(source) Dim type = assembly.GetType("E") Assert.Equal("0", FormatValue(0, type)) Assert.Equal("A {1}", FormatValue(1, type)) Assert.Equal("B {2}", FormatValue(2, type)) Assert.Equal("3", FormatValue(3, type)) End Sub <Fact> Public Sub NonFlagsEnum_Negative() Dim source = " Enum E A = -1 B = -2 End Enum " Dim assembly = GetAssembly(source) Dim type = assembly.GetType("E") Assert.Equal("0", FormatValue(0, type)) Assert.Equal("A {-1}", FormatValue(-1, type)) Assert.Equal("B {-2}", FormatValue(-2, type)) Assert.Equal("-3", FormatValue(-3, type)) End Sub <Fact> Public Sub NonFlagsEnum_Order() Dim source = " Enum E1 A = 1 B = 1 End ENum Enum E2 B = 1 A = 1 End Enum " Dim assembly = GetAssembly(source) Dim e1 = assembly.GetType("E1") Dim e2 = assembly.GetType("E2") ' VB always picks field that is lexically "first" Assert.Equal("A {1}", FormatValue(1, e1)) Assert.Equal("A {1}", FormatValue(1, e2)) End Sub <Fact> Public Sub FlagsEnum() Dim source = " Imports System <Flags> Enum E A = 1 B = 2 End Enum " Dim assembly = GetAssembly(source) Dim type = assembly.GetType("E") Assert.Equal("0", FormatValue(0, type)) Assert.Equal("A {1}", FormatValue(1, type)) Assert.Equal("B {2}", FormatValue(2, type)) Assert.Equal("A Or B {3}", FormatValue(3, type)) Assert.Equal("4", FormatValue(4, type)) End Sub <Fact> Public Sub FlagsEnum_Zero() Dim source = " Imports System <Flags> Enum E None = 0 A = 1 B = 2 End Enum " Dim assembly = GetAssembly(source) Dim type = assembly.GetType("E") Assert.Equal("None {0}", FormatValue(0, type)) Assert.Equal("A {1}", FormatValue(1, type)) Assert.Equal("B {2}", FormatValue(2, type)) Assert.Equal("A Or B {3}", FormatValue(3, type)) Assert.Equal("4", FormatValue(4, type)) End Sub <Fact> Public Sub FlagsEnum_Combination() Dim source = " Imports System <Flags> Enum E None = 0 A = 1 B = 2 C = A Or B End Enum " Dim assembly = GetAssembly(source) Dim type = assembly.GetType("E") Assert.Equal("None {0}", FormatValue(0, type)) Assert.Equal("A {1}", FormatValue(1, type)) Assert.Equal("B {2}", FormatValue(2, type)) Assert.Equal("C {3}", FormatValue(3, type)) Assert.Equal("4", FormatValue(4, type)) End Sub <Fact> Public Sub FlagsEnum_Negative() Dim source = " Imports System <Flags> Enum E None = 0 A = -1 B = -2 End Enum " Dim assembly = GetAssembly(source) Dim type = assembly.GetType("E") Assert.Equal("None {0}", FormatValue(0, type)) Assert.Equal("A {-1}", FormatValue(-1, type)) Assert.Equal("B {-2}", FormatValue(-2, type)) Assert.Equal("-3", FormatValue(-3, type)) Assert.Equal("-4", FormatValue(-4, type)) End Sub <Fact> Public Sub FlagsEnum_Order() Dim source = " Imports System <Flags> Enum E1 A = 1 B = 1 C = 2 D = 2 End Enum <Flags> Enum E2 D = 2 C = 2 B = 1 A = 1 End Enum " Dim assembly = GetAssembly(source) Dim e1 = assembly.GetType("E1") Dim e2 = assembly.GetType("E2") Assert.Equal("0", FormatValue(0, e1)) Assert.Equal("A {1}", FormatValue(1, e1)) Assert.Equal("C {2}", FormatValue(2, e1)) Assert.Equal("A Or C {3}", FormatValue(3, e1)) Assert.Equal("0", FormatValue(0, e2)) Assert.Equal("A {1}", FormatValue(1, e2)) Assert.Equal("C {2}", FormatValue(2, e2)) Assert.Equal("A Or C {3}", FormatValue(3, e2)) End Sub <Fact> Public Sub Arrays() Dim source = " Namespace N Public Class A(Of T) Public Class B(Of U) End Class End Class End Namespace " Dim assembly = GetAssembly(source) Dim typeA = assembly.GetType("N.A`1") Dim typeB = typeA.GetNestedType("B`1") Dim constructedType = typeB.MakeGenericType(GetType(Boolean), GetType(Long)) Dim vectorInstance = Array.CreateInstance(constructedType, 2) Dim matrixInstance = Array.CreateInstance(constructedType, 3, 4) Dim irregularInstance = Array.CreateInstance(constructedType, {1, 2}, {3, 4}) Assert.Equal("{Length=2}", FormatValue(vectorInstance)) Assert.Equal("{Length=12}", FormatValue(matrixInstance)) Assert.Equal("{Length=2}", FormatValue(irregularInstance)) Assert.Equal("{Length=2}", FormatValue(vectorInstance, useHexadecimal:=True)) Assert.Equal("{Length=12}", FormatValue(matrixInstance, useHexadecimal:=True)) Assert.Equal("{Length=2}", FormatValue(irregularInstance, useHexadecimal:=True)) End Sub <Fact> Public Sub Pointers() Dim pointerType = GetType(Integer).MakePointerType() Dim doublePointerType = pointerType.MakePointerType() Assert.Equal("&H00000001", FormatValue(1, pointerType, useHexadecimal:=False)) ' In hex, regardless. Assert.Equal("&H00000001", FormatValue(1, pointerType, useHexadecimal:=True)) Assert.Equal("&HFFFFFFFF", FormatValue(-1, doublePointerType, useHexadecimal:=False)) ' In hex, regardless. Assert.Equal("&HFFFFFFFF", FormatValue(-1, doublePointerType, useHexadecimal:=True)) End Sub <Fact> Public Sub Nullable() Dim source = " Namespace N Public Structure A(Of T) Public Structure B(Of U) Public Overrides Function ToString() As String Return ""ToString() called."" End Function End Structure End Structure End Namespace " Dim assembly = GetAssembly(source) Dim typeA = assembly.GetType("N.A`1") Dim typeB = typeA.GetNestedType("B`1") Dim constructedType = typeB.MakeGenericType(GetType(Boolean), GetType(Long)) Dim nullableType = GetType(Nullable(Of )) Dim nullableConstructedType = nullableType.MakeGenericType(constructedType) Dim nullableInt = nullableType.MakeGenericType(GetType(Integer)) Assert.Equal("Nothing", FormatValue(Nothing, nullableConstructedType)) Assert.Equal("{ToString() called.}", FormatValue(constructedType.Instantiate(), nullableConstructedType)) Assert.Equal("Nothing", FormatValue(Nothing, nullableInt)) Assert.Equal("1", FormatValue(1, nullableInt)) End Sub <Fact> Public Sub ToStringOverrides() Dim source = " Public Class A(Of T) End Class Public Class B : Inherits A(Of Integer) Public Overrides Function ToString() As String Return ""B.ToString()"" End Function End Class Public Class C : Inherits B End Class " Dim assembly = GetAssembly(source) Dim typeC = assembly.GetType("C") Dim typeB = assembly.GetType("B") Dim typeA = typeB.BaseType Assert.Equal("Nothing", FormatValue(Nothing, typeA)) Assert.Equal("Nothing", FormatValue(Nothing, typeB)) Assert.Equal("Nothing", FormatValue(Nothing, typeC)) Assert.Equal("{A(Of Integer)}", FormatValue(typeA.Instantiate())) Assert.Equal("{B.ToString()}", FormatValue(typeB.Instantiate())) Assert.Equal("{B.ToString()}", FormatValue(typeC.Instantiate())) End Sub <Fact> Public Sub ValuesWithUnderlyingString() Assert.True(HasUnderlyingString("Test")) Assert.False(HasUnderlyingString(Nothing, GetType(String))) Assert.False(HasUnderlyingString(0)) Assert.False(HasUnderlyingString(DkmEvaluationFlags.None)) ' Enum Assert.False(HasUnderlyingString("a"c)) Assert.False(HasUnderlyingString({1, 2, 3})) Assert.False(HasUnderlyingString(New Object())) Assert.False(HasUnderlyingString(0, GetType(Integer).MakePointerType())) End Sub <Fact> Public Sub VisualizeString() Assert.Equal(vbCrLf, GetUnderlyingString(vbCrLf)) End Sub <Fact> Public Sub VisualizeSqlString() Dim source = " Namespace System.Data.SqlTypes Public Structure SqlString Private m_value As String Public Sub New(data As String) m_value = data End Sub End Structure End Namespace " Dim assembly = GetAssembly(source) Dim type = assembly.GetType("System.Data.SqlTypes.SqlString") Dim sqlString = type.Instantiate({"Test"}) Assert.Equal("Test", GetUnderlyingString(sqlString)) End Sub <Fact> Public Sub VisualizeXNode() Dim source = " Namespace System.Xml.Linq Public Class XNode Public Overrides Function ToString() As String Return ""Test1"" End Function End Class Public Class XContainer : Inherits XNode End Class Public Class XElement : Inherits XContainer Public Overrides Function ToString() As String Return ""Test2"" End Function End Class End Namespace " Dim assembly = GetAssembly(source) Dim xnType = assembly.GetType("System.Xml.Linq.XNode") Dim xeType = assembly.GetType("System.Xml.Linq.XElement") Assert.Equal("Test1", GetUnderlyingString(xnType.Instantiate())) Assert.Equal("Test2", GetUnderlyingString(xeType.Instantiate())) End Sub <Fact> Public Sub Dates() Assert.Equal("#1/1/0001 12:00:00 AM#", FormatValue(New Date(0))) Assert.Equal("#1/1/1970 12:00:00 AM#", FormatValue(New Date(1970, 1, 1))) Assert.Equal("#1/1/0001 12:00:00 PM#", FormatValue(New Date(1, 1, 1, 12, 0, 0, 0))) Assert.Equal("#1/1/0001 12:00:00 PM#", FormatValue(New Date(1, 1, 1, 12, 0, 0, 0), useHexadecimal:=True)) ' Hexadecimal setting shouldn't change output ' DateTimeKind is stored in the top two bits of the ULong value that backs the DateTime instance. ' We need to make sure we don't throw an Exception when those bits are set to non-zero values. Assert.Equal("#1/1/1970 12:00:00 AM#", FormatValue(New Date(&H89F7FF5F7B58000, DateTimeKind.Local))) Assert.Equal("#1/1/1970 12:00:00 AM#", FormatValue(New Date(&H89F7FF5F7B58000, DateTimeKind.Utc))) End Sub <Fact> Public Sub HostValueNotFound_Integer() Dim clrValue = New DkmClrValue(value:=Nothing, hostObjectValue:=Nothing, New DkmClrType(CType(GetType(Integer), TypeImpl)), alias:=Nothing, evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.None) Assert.Equal(Resources.HostValueNotFound, FormatValue(clrValue)) End Sub <Fact> Public Sub HostValueNotFound_char() Dim clrValue = New DkmClrValue(value:=Nothing, hostObjectValue:=Nothing, New DkmClrType(CType(GetType(Char), TypeImpl)), alias:=Nothing, evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.None) Assert.Equal(Resources.HostValueNotFound, FormatValue(clrValue)) End Sub <Fact> Public Sub HostValueNotFound_IntPtr() Dim clrValue = New DkmClrValue(value:=Nothing, hostObjectValue:=Nothing, New DkmClrType(CType(GetType(IntPtr), TypeImpl)), alias:=Nothing, evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.None) Assert.Equal(Resources.HostValueNotFound, FormatValue(clrValue)) End Sub <Fact> Public Sub HostValueNotFound_UIntPtr() Dim clrValue = New DkmClrValue(value:=Nothing, hostObjectValue:=Nothing, New DkmClrType(CType(GetType(UIntPtr), TypeImpl)), alias:=Nothing, evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.None) Assert.Equal(Resources.HostValueNotFound, FormatValue(clrValue)) End Sub <Fact> Public Sub HostValueNotFound_Enum() Dim clrValue = New DkmClrValue(value:=Nothing, hostObjectValue:=Nothing, New DkmClrType(CType(GetType(TestEnum), TypeImpl)), alias:=Nothing, evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.None) Assert.Equal(Resources.HostValueNotFound, FormatValue(clrValue)) End Sub ' DateTime is a primitive type in VB but not in C#. <Fact> Public Sub HostValueNotFound_DateTime() Dim clrValue = New DkmClrValue(value:=Nothing, hostObjectValue:=Nothing, New DkmClrType(CType(GetType(DateTime), TypeImpl)), alias:=Nothing, evalFlags:=DkmEvaluationResultFlags.None, valueFlags:=DkmClrValueFlags.None) Assert.Equal(Resources.HostValueNotFound, FormatValue(clrValue)) End Sub Private Enum TestEnum One End Enum End Class End Namespace