|
' 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 System.IO
Imports System.Reflection.Metadata
Imports System.Reflection.PortableExecutable
Imports System.Security.Cryptography
Imports System.Text
Imports Microsoft.CodeAnalysis.Debugging
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.PDB
Public Class PortablePdbTests
Inherits BasicTestBase
<Fact()>
Public Sub DateTimeConstant()
Dim source = <compilation>
<file>
Imports System
Public Class C
Public Sub M()
const dt1 as datetime = #3/01/2016#
const dt2 as datetime = #10:53:37 AM#
const dt3 as datetime = #3/01/2016 10:53:37 AM#
End Sub
End Class
</file>
</compilation>
Dim compilation = CompilationUtils.CreateCompilationWithMscorlib40AndVBRuntime(
source,
TestOptions.DebugDll)
Dim pdbStream = New MemoryStream()
compilation.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream:=pdbStream)
Using pdbMetadata As New PinnedMetadata(pdbStream.ToImmutable())
Dim mdReader = pdbMetadata.Reader
Assert.Equal(3, mdReader.LocalConstants.Count)
For Each constantHandle In mdReader.LocalConstants
Dim constant = mdReader.GetLocalConstant(constantHandle)
Dim sigReader = mdReader.GetBlobReader(constant.Signature)
' DateTime constants are always SignatureTypeCode.ValueType {17}
Dim rawTypeCode = sigReader.ReadCompressedInteger()
Assert.Equal(17, rawTypeCode)
' DateTime constants are always HandleKind.TypeReference {1}
Dim typeHandle = sigReader.ReadTypeHandle()
Assert.Equal(HandleKind.TypeReference, typeHandle.Kind)
' DateTime constants are always stored and retrieved with no time zone specification
Dim value = sigReader.ReadDateTime()
Assert.Equal(DateTimeKind.Unspecified, value.Kind)
Next
End Using
End Sub
<Fact>
Public Sub EmbeddedPortablePdb()
Dim source = "
Imports System
Class C
Public Shared Sub Main()
Console.WriteLine()
End Sub
End Class
"
Dim c = CreateCompilationWithMscorlib40(Parse(source, "goo.vb"), options:=TestOptions.DebugDll)
Dim peBlob = c.EmitToArray(EmitOptions.Default.
WithDebugInformationFormat(DebugInformationFormat.Embedded).
WithPdbFilePath("a/b/c/d.pdb").
WithPdbChecksumAlgorithm(HashAlgorithmName.SHA512))
Using peReader = New PEReader(peBlob)
Dim entries = peReader.ReadDebugDirectory()
AssertEx.Equal({DebugDirectoryEntryType.CodeView, DebugDirectoryEntryType.PdbChecksum, DebugDirectoryEntryType.EmbeddedPortablePdb}, entries.Select(Function(e) e.Type))
Dim codeView = entries(0)
Dim checksum = entries(1)
Dim embedded = entries(2)
' EmbeddedPortablePdb entry
Assert.Equal(&H100, embedded.MajorVersion)
Assert.Equal(&H100, embedded.MinorVersion)
Assert.Equal(CUInt(0), embedded.Stamp)
Dim pdbId As BlobContentId
Using embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embedded)
Dim mdReader = embeddedMetadataProvider.GetMetadataReader()
AssertEx.Equal({"goo.vb"}, mdReader.Documents.Select(Function(doc) mdReader.GetString(mdReader.GetDocument(doc).Name)))
pdbId = New BlobContentId(mdReader.DebugMetadataHeader.Id)
End Using
' CodeView entry:
Dim codeViewData = peReader.ReadCodeViewDebugDirectoryData(codeView)
Assert.Equal(&H100, codeView.MajorVersion)
Assert.Equal(&H504D, codeView.MinorVersion)
Assert.Equal(pdbId.Stamp, codeView.Stamp)
Assert.Equal(pdbId.Guid, codeViewData.Guid)
Assert.Equal("d.pdb", codeViewData.Path)
' Checksum entry
Dim checksumData = peReader.ReadPdbChecksumDebugDirectoryData(checksum)
Assert.Equal("SHA512", checksumData.AlgorithmName)
Assert.Equal(64, checksumData.Checksum.Length)
End Using
End Sub
<Fact>
Public Sub EmbeddedPortablePdb_Deterministic()
Dim source = "
Imports System
Class C
Public Shared Sub Main()
Console.WriteLine()
End Sub
End Class
"
Dim c = CreateCompilationWithMscorlib40(Parse(source, "goo.vb"), options:=TestOptions.DebugDll.WithDeterministic(True))
Dim peBlob = c.EmitToArray(EmitOptions.Default.
WithDebugInformationFormat(DebugInformationFormat.Embedded).
WithPdbChecksumAlgorithm(HashAlgorithmName.SHA384).
WithPdbFilePath("a/b/c/d.pdb"))
Using peReader = New PEReader(peBlob)
Dim entries = peReader.ReadDebugDirectory()
AssertEx.Equal({DebugDirectoryEntryType.CodeView, DebugDirectoryEntryType.PdbChecksum, DebugDirectoryEntryType.Reproducible, DebugDirectoryEntryType.EmbeddedPortablePdb}, entries.Select(Function(e) e.Type))
Dim codeView = entries(0)
Dim checksum = entries(1)
Dim reproducible = entries(2)
Dim embedded = entries(3)
' EmbeddedPortablePdb entry
Assert.Equal(&H100, embedded.MajorVersion)
Assert.Equal(&H100, embedded.MinorVersion)
Assert.Equal(CUInt(0), embedded.Stamp)
Dim pdbId As BlobContentId
Using embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embedded)
Dim mdReader = embeddedMetadataProvider.GetMetadataReader()
AssertEx.Equal({"goo.vb"}, mdReader.Documents.Select(Function(doc) mdReader.GetString(mdReader.GetDocument(doc).Name)))
pdbId = New BlobContentId(mdReader.DebugMetadataHeader.Id)
End Using
' CodeView entry:
Dim codeViewData = peReader.ReadCodeViewDebugDirectoryData(codeView)
Assert.Equal(&H100, codeView.MajorVersion)
Assert.Equal(&H504D, codeView.MinorVersion)
Assert.Equal(pdbId.Stamp, codeView.Stamp)
Assert.Equal(pdbId.Guid, codeViewData.Guid)
Assert.Equal("d.pdb", codeViewData.Path)
' Checksum entry
Dim checksumData = peReader.ReadPdbChecksumDebugDirectoryData(checksum)
Assert.Equal("SHA384", checksumData.AlgorithmName)
Assert.Equal(48, checksumData.Checksum.Length)
' Reproducible entry
Assert.Equal(0, reproducible.MajorVersion)
Assert.Equal(0, reproducible.MinorVersion)
Assert.Equal(CUInt(0), reproducible.Stamp)
Assert.Equal(0, reproducible.DataSize)
End Using
End Sub
<Fact>
Public Sub SourceLink()
Dim source = "
Imports System
Class C
Public Shared Sub Main()
Console.WriteLine()
End Sub
End Class
"
Dim sourceLinkBlob = Encoding.UTF8.GetBytes("
{
""documents"": {
""f:/build/*"" : ""https://raw.githubusercontent.com/my-org/my-project/1111111111111111111111111111111111111111/*"";
}
}
")
Dim c = CreateCompilationWithMscorlib40(Parse(source, "f:/build/goo.vb"), options:=TestOptions.DebugDll)
Dim pdbStream = New MemoryStream()
c.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream:=pdbStream, sourceLinkStream:=New MemoryStream(sourceLinkBlob))
pdbStream.Position = 0
Using provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream)
Dim pdbReader = provider.GetMetadataReader()
Dim actualBlob =
(From cdiHandle In pdbReader.GetCustomDebugInformation(EntityHandle.ModuleDefinition)
Let cdi = pdbReader.GetCustomDebugInformation(cdiHandle)
Where pdbReader.GetGuid(cdi.Kind) = PortableCustomDebugInfoKinds.SourceLink
Select pdbReader.GetBlobBytes(cdi.Value)).Single()
AssertEx.Equal(sourceLinkBlob, actualBlob)
End Using
End Sub
<Fact>
Public Sub SourceLink_Embedded()
Dim source = "
Imports System
Class C
Public Shared Sub Main()
Console.WriteLine()
End Sub
End Class
"
Dim sourceLinkBlob = Encoding.UTF8.GetBytes("
{
""documents"": {
""f:/build/*"" : ""https://raw.githubusercontent.com/my-org/my-project/1111111111111111111111111111111111111111/*"";
}
}
")
Dim c = CreateCompilationWithMscorlib40(Parse(source, "f:/build/goo.vb"), options:=TestOptions.DebugDll)
Dim peBlob = c.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.Embedded), sourceLinkStream:=New MemoryStream(sourceLinkBlob))
Using peReader = New PEReader(peBlob)
Dim embeddedEntry = peReader.ReadDebugDirectory().Single(Function(e) e.Type = DebugDirectoryEntryType.EmbeddedPortablePdb)
Using embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedEntry)
Dim pdbReader = embeddedMetadataProvider.GetMetadataReader()
Dim actualBlob =
(From cdiHandle In pdbReader.GetCustomDebugInformation(EntityHandle.ModuleDefinition)
Let cdi = pdbReader.GetCustomDebugInformation(cdiHandle)
Where pdbReader.GetGuid(cdi.Kind) = PortableCustomDebugInfoKinds.SourceLink
Select pdbReader.GetBlobBytes(cdi.Value)).Single()
AssertEx.Equal(sourceLinkBlob, actualBlob)
End Using
End Using
End Sub
<Fact>
Public Sub SourceLink_Errors()
Dim source = "
Imports System
Class C
Public Shared Sub Main()
Console.WriteLine()
End Sub
End Class
"
Dim sourceLinkStream = New TestStream(canRead:=True, readFunc:=Function(a1, a2, a3)
Throw New Exception("Error!")
End Function)
Dim c = CreateCompilationWithMscorlib40(Parse(source, "f:/build/goo.vb"), options:=TestOptions.DebugDll)
Dim result = c.Emit(New MemoryStream(), New MemoryStream(), options:=EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), sourceLinkStream:=sourceLinkStream)
result.Diagnostics.Verify(
Diagnostic(ERRID.ERR_PDBWritingFailed).WithArguments("Error!").WithLocation(1, 1))
End Sub
End Class
End Namespace
|