File: Reader\MockSymUnmanagedReader.cs
Web Access
Project: src\src\Test\PdbUtilities\Roslyn.Test.PdbUtilities.csproj (Roslyn.Test.PdbUtilities)
// 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.
 
#nullable disable
 
extern alias DSR;
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;
using DSR::Microsoft.DiaSymReader;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
using Xunit;
 
namespace Roslyn.Test.Utilities
{
    internal sealed class MockSymUnmanagedReader : ISymUnmanagedReader, ISymUnmanagedReader2, ISymUnmanagedReader3
    {
        private readonly ImmutableDictionary<int, MethodDebugInfoBytes> _methodDebugInfoMap;
 
        public MockSymUnmanagedReader(ImmutableDictionary<int, MethodDebugInfoBytes> methodDebugInfoMap)
        {
            _methodDebugInfoMap = methodDebugInfoMap;
        }
 
        public int GetMethod(int methodToken, out ISymUnmanagedMethod method)
        {
            return GetMethodByVersion(methodToken, 1, out method);
        }
 
        public int GetMethodByVersion(int methodToken, int version, out ISymUnmanagedMethod retVal)
        {
            Assert.Equal(1, version);
 
            MethodDebugInfoBytes info;
            if (!_methodDebugInfoMap.TryGetValue(methodToken, out info))
            {
                retVal = null;
                return HResult.E_FAIL;
            }
 
            Assert.NotNull(info);
            retVal = info.Method;
            return HResult.S_OK;
        }
 
        public int GetSymAttribute(int methodToken, string name, int bufferLength, out int count, byte[] customDebugInformation)
        {
            // The EE should never be calling ISymUnmanagedReader.GetSymAttribute.  
            // In order to account for EnC updates, it should always be calling 
            // ISymUnmanagedReader3.GetSymAttributeByVersion instead.
            throw ExceptionUtilities.Unreachable();
        }
 
        public int GetSymAttributeByVersion(int methodToken, int version, string name, int bufferLength, out int count, byte[] customDebugInformation)
        {
            Assert.Equal(1, version);
 
            Assert.Equal("MD2", name);
 
            MethodDebugInfoBytes info;
            if (!_methodDebugInfoMap.TryGetValue(methodToken, out info))
            {
                count = 0;
                return HResult.S_FALSE; // This is a guess.  We're not consuming it, so it doesn't really matter.
            }
 
            Assert.NotNull(info);
            info.Bytes.TwoPhaseCopy(bufferLength, out count, customDebugInformation);
            return HResult.S_OK;
        }
 
        public int GetDocument(string url, Guid language, Guid languageVendor, Guid documentType, out ISymUnmanagedDocument document)
        {
            throw new NotImplementedException();
        }
 
        public int GetDocuments(int bufferLength, out int count, ISymUnmanagedDocument[] documents)
        {
            throw new NotImplementedException();
        }
 
        public int GetUserEntryPoint(out int methodToken)
        {
            throw new NotImplementedException();
        }
 
        public int GetVariables(int methodToken, int bufferLength, out int count, ISymUnmanagedVariable[] variables)
        {
            throw new NotImplementedException();
        }
 
        public int GetGlobalVariables(int bufferLength, out int count, ISymUnmanagedVariable[] variables)
        {
            throw new NotImplementedException();
        }
 
        public int GetMethodFromDocumentPosition(ISymUnmanagedDocument document, int line, int column, out ISymUnmanagedMethod method)
        {
            throw new NotImplementedException();
        }
 
        public int GetNamespaces(int bufferLength, out int count, ISymUnmanagedNamespace[] namespaces)
        {
            throw new NotImplementedException();
        }
 
        public int Initialize(object metadataImporter, string fileName, string searchPath, IStream stream)
        {
            throw new NotImplementedException();
        }
 
        public int UpdateSymbolStore(string fileName, IStream stream)
        {
            throw new NotImplementedException();
        }
 
        public int ReplaceSymbolStore(string fileName, IStream stream)
        {
            throw new NotImplementedException();
        }
 
        public int GetSymbolStoreFileName(int bufferLength, out int count, char[] name)
        {
            throw new NotImplementedException();
        }
 
        public int GetMethodsFromDocumentPosition(ISymUnmanagedDocument document, int line, int column, int bufferLength, out int count, ISymUnmanagedMethod[] methods)
        {
            throw new NotImplementedException();
        }
 
        public int GetDocumentVersion(ISymUnmanagedDocument document, out int version, out bool isCurrent)
        {
            throw new NotImplementedException();
        }
 
        public int GetMethodVersion(ISymUnmanagedMethod method, out int version)
        {
            throw new NotImplementedException();
        }
 
        public int GetMethodByVersionPreRemap(int methodToken, int version, out ISymUnmanagedMethod method)
        {
            throw new NotImplementedException();
        }
 
        public int GetSymAttributePreRemap(int methodToken, string name, int bufferLength, out int count, byte[] customDebugInformation)
        {
            throw new NotImplementedException();
        }
 
        public int GetMethodsInDocument(ISymUnmanagedDocument document, int bufferLength, out int count, ISymUnmanagedMethod[] methods)
        {
            throw new NotImplementedException();
        }
 
        public int GetSymAttributeByVersionPreRemap(int methodToken, int version, string name, int bufferLength, out int count, byte[] customDebugInformation)
        {
            throw new NotImplementedException();
        }
    }
 
    internal sealed class MockSymUnmanagedMethod : ISymUnmanagedMethod
    {
        private readonly ISymUnmanagedScope _rootScope;
 
        public MockSymUnmanagedMethod(ISymUnmanagedScope rootScope)
        {
            _rootScope = rootScope;
        }
 
        int ISymUnmanagedMethod.GetRootScope(out ISymUnmanagedScope retVal)
        {
            retVal = _rootScope;
            return HResult.S_OK;
        }
 
        int ISymUnmanagedMethod.GetSequencePointCount(out int retVal)
        {
            retVal = 1;
            return HResult.S_OK;
        }
 
        int ISymUnmanagedMethod.GetSequencePoints(int cPoints, out int pcPoints, int[] offsets, ISymUnmanagedDocument[] documents, int[] lines, int[] columns, int[] endLines, int[] endColumns)
        {
            pcPoints = 1;
            offsets[0] = 0;
            documents[0] = null;
            lines[0] = 0;
            columns[0] = 0;
            endLines[0] = 0;
            endColumns[0] = 0;
            return HResult.S_OK;
        }
 
        int ISymUnmanagedMethod.GetNamespace(out ISymUnmanagedNamespace retVal)
        {
            throw new NotImplementedException();
        }
 
        int ISymUnmanagedMethod.GetOffset(ISymUnmanagedDocument document, int line, int column, out int retVal)
        {
            throw new NotImplementedException();
        }
 
        int ISymUnmanagedMethod.GetParameters(int cParams, out int pcParams, ISymUnmanagedVariable[] parms)
        {
            throw new NotImplementedException();
        }
 
        int ISymUnmanagedMethod.GetRanges(ISymUnmanagedDocument document, int line, int column, int cRanges, out int pcRanges, int[] ranges)
        {
            throw new NotImplementedException();
        }
 
        int ISymUnmanagedMethod.GetScopeFromOffset(int offset, out ISymUnmanagedScope retVal)
        {
            throw new NotImplementedException();
        }
 
        int ISymUnmanagedMethod.GetSourceStartEnd(ISymUnmanagedDocument[] docs, int[] lines, int[] columns, out bool retVal)
        {
            throw new NotImplementedException();
        }
 
        int ISymUnmanagedMethod.GetToken(out int pToken)
        {
            throw new NotImplementedException();
        }
    }
 
    internal sealed class MockSymUnmanagedScope : ISymUnmanagedScope, ISymUnmanagedScope2
    {
        private readonly ImmutableArray<ISymUnmanagedScope> _children;
        private readonly ImmutableArray<ISymUnmanagedNamespace> _namespaces;
        private readonly ISymUnmanagedConstant[] _constants;
        private readonly int _startOffset;
        private readonly int _endOffset;
 
        public MockSymUnmanagedScope(ImmutableArray<ISymUnmanagedScope> children, ImmutableArray<ISymUnmanagedNamespace> namespaces, ISymUnmanagedConstant[] constants = null, int startOffset = 0, int endOffset = 1)
        {
            _children = children;
            _namespaces = namespaces;
            _constants = constants ?? new ISymUnmanagedConstant[0];
            _startOffset = startOffset;
            _endOffset = endOffset;
        }
 
        public int GetChildren(int numDesired, out int numRead, ISymUnmanagedScope[] buffer)
        {
            _children.TwoPhaseCopy(numDesired, out numRead, buffer);
            return HResult.S_OK;
        }
 
        public int GetNamespaces(int numDesired, out int numRead, ISymUnmanagedNamespace[] buffer)
        {
            _namespaces.TwoPhaseCopy(numDesired, out numRead, buffer);
            return HResult.S_OK;
        }
 
        public int GetStartOffset(out int pRetVal)
        {
            pRetVal = _startOffset;
            return HResult.S_OK;
        }
 
        public int GetEndOffset(out int pRetVal)
        {
            pRetVal = _endOffset;
            return HResult.S_OK;
        }
 
        public int GetLocalCount(out int pRetVal)
        {
            pRetVal = 0;
            return HResult.S_OK;
        }
 
        public int GetLocals(int cLocals, out int pcLocals, ISymUnmanagedVariable[] locals)
        {
            pcLocals = 0;
            return HResult.S_OK;
        }
 
        public int GetMethod(out ISymUnmanagedMethod pRetVal)
        {
            throw new NotImplementedException();
        }
 
        public int GetParent(out ISymUnmanagedScope pRetVal)
        {
            throw new NotImplementedException();
        }
 
        public int GetConstantCount(out int pRetVal)
        {
            pRetVal = _constants.Length;
            return HResult.S_OK;
        }
 
        public int GetConstants(int cConstants, out int pcConstants, ISymUnmanagedConstant[] constants)
        {
            pcConstants = _constants.Length;
            if (constants != null)
            {
                Array.Copy(_constants, constants, constants.Length);
            }
            return HResult.S_OK;
        }
    }
 
    internal sealed class MockSymUnmanagedNamespace : ISymUnmanagedNamespace
    {
        private readonly ImmutableArray<char> _nameChars;
 
        public MockSymUnmanagedNamespace(string name)
        {
            if (name != null)
            {
                var builder = ArrayBuilder<char>.GetInstance();
                builder.AddRange(name);
                builder.AddRange('\0');
                _nameChars = builder.ToImmutableAndFree();
            }
        }
 
        int ISymUnmanagedNamespace.GetName(int numDesired, out int numRead, char[] buffer)
        {
            _nameChars.TwoPhaseCopy(numDesired, out numRead, buffer);
            return 0;
        }
 
        int ISymUnmanagedNamespace.GetNamespaces(int cNameSpaces, out int pcNameSpaces, ISymUnmanagedNamespace[] namespaces)
        {
            throw new NotImplementedException();
        }
 
        int ISymUnmanagedNamespace.GetVariables(int cVars, out int pcVars, ISymUnmanagedVariable[] pVars)
        {
            throw new NotImplementedException();
        }
    }
 
    internal delegate int GetSignatureDelegate(int bufferLength, out int count, byte[] signature);
 
    internal sealed class MockSymUnmanagedConstant : ISymUnmanagedConstant
    {
        private readonly string _name;
        private readonly object _value;
        private readonly GetSignatureDelegate _getSignature;
 
        public MockSymUnmanagedConstant(string name, object value, GetSignatureDelegate getSignature)
        {
            _name = name;
            _value = value;
            _getSignature = getSignature;
        }
 
        int ISymUnmanagedConstant.GetName(int bufferLength, out int count, char[] name)
        {
            count = _name.Length + 1; // + 1 for null terminator
            Debug.Assert((bufferLength == 0) || (bufferLength == count));
            for (int i = 0; i < bufferLength - 1; i++)
            {
                name[i] = _name[i];
            }
            return HResult.S_OK;
        }
 
        int ISymUnmanagedConstant.GetSignature(int bufferLength, out int count, byte[] signature)
        {
            return _getSignature(bufferLength, out count, signature);
        }
 
        int ISymUnmanagedConstant.GetValue(out object value)
        {
            value = _value;
            return HResult.S_OK;
        }
    }
 
    internal static class MockSymUnmanagedHelpers
    {
        public static void TwoPhaseCopy<T>(this ImmutableArray<T> source, int numDesired, out int numRead, T[] destination)
        {
            if (destination == null)
            {
                Assert.Equal(0, numDesired);
                numRead = source.IsDefault ? 0 : source.Length;
            }
            else
            {
                Assert.False(source.IsDefault);
                Assert.Equal(source.Length, numDesired);
                source.CopyTo(0, destination, 0, numDesired);
                numRead = numDesired;
            }
        }
 
        public static void Add2(this ArrayBuilder<byte> bytes, short s)
        {
            var shortBytes = BitConverter.GetBytes(s);
            Assert.Equal(2, shortBytes.Length);
            bytes.AddRange(shortBytes);
        }
 
        public static void Add4(this ArrayBuilder<byte> bytes, int i)
        {
            var intBytes = BitConverter.GetBytes(i);
            Assert.Equal(4, intBytes.Length);
            bytes.AddRange(intBytes);
        }
    }
}