Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Max Charlamb committed Dec 2, 2024
1 parent 15c0dac commit 7a104d0
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 1 deletion.
105 changes: 105 additions & 0 deletions src/native/managed/cdacreader/tests/GCCoverTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Diagnostics.DataContractReader.Contracts;
using Microsoft.Diagnostics.DataContractReader.Contracts.Extensions;
using Microsoft.Diagnostics.DataContractReader.Data;
using Moq;
using Xunit;

namespace Microsoft.Diagnostics.DataContractReader.Tests;

using MockGCCover = MockDescriptors.GCCover;

public class GCCoverTests
{
internal static Target CreateTarget(
MockTarget.Architecture arch,
MockGCCover builder,
Mock<IRuntimeTypeSystem> mockRuntimeTypeSystem = null)
{
TestPlaceholderTarget target = new TestPlaceholderTarget(arch, builder.Builder.GetReadContext().ReadFromTarget, builder.Types, builder.Globals);

mockRuntimeTypeSystem ??= new Mock<IRuntimeTypeSystem>();

IContractFactory<IGCCover> gcCoverFactory = new GCCoverFactory();

ContractRegistry reg = Mock.Of<ContractRegistry>(
c => c.GCCover == gcCoverFactory.CreateContract(target, 1)
&& c.RuntimeTypeSystem == mockRuntimeTypeSystem.Object);
target.SetContracts(reg);
return target;
}

[Theory]
[ClassData(typeof(MockTarget.StdArch))]
public void GetGCCoverageInfo_Explicit(MockTarget.Architecture arch)
{
GetGCCoverageInfoExplicitHelper(arch, new TargetPointer(0x1234_5678));
GetGCCoverageInfoExplicitHelper(arch, TargetPointer.Null);
}

private void GetGCCoverageInfoExplicitHelper(MockTarget.Architecture arch, TargetPointer expectedGCCoverageInfo)
{
MockGCCover mockGCCover = new(arch);

NativeCodeVersionHandle codeVersionHandle = mockGCCover.AddExplicitNativeCodeVersion(expectedGCCoverageInfo);

var target = CreateTarget(arch, mockGCCover);

// TEST

var gcCover = target.Contracts.GCCover;
Assert.NotNull(gcCover);

TargetPointer? actualGCCoverageInfo = gcCover.GetGCCoverageInfo(codeVersionHandle);

Assert.NotNull(actualGCCoverageInfo);
Assert.Equal(expectedGCCoverageInfo, actualGCCoverageInfo);
}

[Theory]
[ClassData(typeof(MockTarget.StdArch))]
public void GetGCCoverageInfo_Synthetic(MockTarget.Architecture arch)
{
GetGCCoverageInfoSyntheticHelper(arch, new TargetPointer(0x1234_5678));
GetGCCoverageInfoSyntheticHelper(arch, TargetPointer.Null);
}


private void GetGCCoverageInfoSyntheticHelper(MockTarget.Architecture arch, TargetPointer expectedGCCoverageInfo)
{
Mock<IRuntimeTypeSystem> mockRTS = new Mock<IRuntimeTypeSystem>();

TargetPointer methodDesc = new(/* arbitrary */ 0x1234_5678);
MockSyntheticGCCoverageInfo(mockRTS, methodDesc, expectedGCCoverageInfo);

NativeCodeVersionHandle codeVersionHandle = NativeCodeVersionHandle.OfSynthetic(methodDesc);

var target = CreateTarget(arch, new MockGCCover(arch), mockRTS);

// TEST

var gcCover = target.Contracts.GCCover;
Assert.NotNull(gcCover);

TargetPointer? actualGCCoverageInfo = gcCover.GetGCCoverageInfo(codeVersionHandle);

Assert.NotNull(actualGCCoverageInfo);
Assert.Equal(expectedGCCoverageInfo, actualGCCoverageInfo);
}

private void MockSyntheticGCCoverageInfo(Mock<IRuntimeTypeSystem> mockRTS, TargetPointer methodDescAddress, TargetPointer expectedGCCoverageInfo)
{
MethodDescHandle methodDescHandle = new MethodDescHandle(methodDescAddress);
mockRTS.Setup(rts => rts
.GetMethodDescHandle(methodDescAddress))
.Returns(methodDescHandle);
mockRTS.Setup(rts => rts
.GetGCCoverageInfo(methodDescHandle))
.Returns(expectedGCCoverageInfo);
}
}
3 changes: 3 additions & 0 deletions src/native/managed/cdacreader/tests/MethodDescTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ public void MethodDescGetMethodDescTokenOk(MockTarget.Architecture arch)
Assert.False(isCollectible);
TargetPointer versioning = rts.GetMethodDescVersioningState(handle);
Assert.Equal(TargetPointer.Null, versioning);
TargetPointer? gcCoverageInfo = rts.GetGCCoverageInfo(handle);
Assert.NotNull(gcCoverageInfo);
Assert.Equal(TargetPointer.Null, gcCoverageInfo.Value);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class CodeVersions
new(nameof(Data.NativeCodeVersionNode.NativeCode), DataType.pointer),
new(nameof(Data.NativeCodeVersionNode.Flags), DataType.uint32),
new(nameof(Data.NativeCodeVersionNode.ILVersionId), DataType.nuint),
new(nameof(Data.NativeCodeVersionNode.GCCoverageInfo), DataType.pointer),
]
};

Expand Down Expand Up @@ -116,7 +117,7 @@ public TargetPointer AddNativeCodeVersionNode()
return fragment.Address;
}

public void FillNativeCodeVersionNode(TargetPointer dest, TargetPointer methodDesc, TargetCodePointer nativeCode, TargetPointer next, bool isActive, TargetNUInt ilVersionId)
public void FillNativeCodeVersionNode(TargetPointer dest, TargetPointer methodDesc, TargetCodePointer nativeCode, TargetPointer next, bool isActive, TargetNUInt ilVersionId, TargetPointer? gcCoverageInfo = null)
{
Target.TypeInfo info = Types[DataType.NativeCodeVersionNode];
Span<byte> ncvn = Builder.BorrowAddressRange(dest, (int)info.Size!);
Expand All @@ -125,6 +126,7 @@ public void FillNativeCodeVersionNode(TargetPointer dest, TargetPointer methodDe
Builder.TargetTestHelpers.WritePointer(ncvn.Slice(info.Fields[nameof(Data.NativeCodeVersionNode.NativeCode)].Offset, Builder.TargetTestHelpers.PointerSize), nativeCode);
Builder.TargetTestHelpers.Write(ncvn.Slice(info.Fields[nameof(Data.NativeCodeVersionNode.Flags)].Offset, sizeof(uint)), isActive ? (uint)CodeVersions_1.NativeCodeVersionNodeFlags.IsActiveChild : 0u);
Builder.TargetTestHelpers.WriteNUInt(ncvn.Slice(info.Fields[nameof(Data.NativeCodeVersionNode.ILVersionId)].Offset, Builder.TargetTestHelpers.PointerSize), ilVersionId);
Builder.TargetTestHelpers.WritePointer(ncvn.Slice(info.Fields[nameof(Data.NativeCodeVersionNode.GCCoverageInfo)].Offset, Builder.TargetTestHelpers.PointerSize), gcCoverageInfo ?? TargetPointer.Null);
}

public (TargetPointer First, TargetPointer Active) AddNativeCodeVersionNodesForMethod(TargetPointer methodDesc, int count, int activeIndex, TargetCodePointer activeNativeCode, TargetNUInt ilVersion, TargetPointer? firstNode = null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using Microsoft.Diagnostics.DataContractReader.Contracts;

namespace Microsoft.Diagnostics.DataContractReader.Tests;

internal partial class MockDescriptors
{
public class GCCover
{
private const ulong DefaultAllocationRangeStart = 0x0011_1000;
private const ulong DefaultAllocationRangeEnd = 0x00012_0000;

internal readonly MockMemorySpace.Builder Builder;

internal Dictionary<DataType, Target.TypeInfo> Types { get; }
internal (string Name, ulong Value)[] Globals { get; }

private CodeVersions _codeVersions { get; }
public GCCover(MockTarget.Architecture arch)
: this(new MockMemorySpace.Builder(new TargetTestHelpers(arch)))
{ }

public GCCover(MockMemorySpace.Builder builder)
{
Builder = builder;

_codeVersions = new CodeVersions(Builder);

Types = CodeVersions.GetTypes(builder.TargetTestHelpers);
}

public NativeCodeVersionHandle AddExplicitNativeCodeVersion(TargetPointer gcCoverPointer)
{
TargetPointer nativeCodeVersionNode = _codeVersions.AddNativeCodeVersionNode();
_codeVersions.FillNativeCodeVersionNode(
nativeCodeVersionNode,
TargetPointer.Null,
TargetCodePointer.Null,
TargetPointer.Null,
true,
new(1),
gcCoverPointer);

return NativeCodeVersionHandle.OfExplicit(nativeCodeVersionNode);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class MethodDescriptors
new(nameof(Data.MethodDesc.Flags3AndTokenRemainder), DataType.uint16),
new(nameof(Data.MethodDesc.EntryPointFlags), DataType.uint8),
new(nameof(Data.MethodDesc.CodeData), DataType.pointer),
new(nameof(Data.MethodDesc.GCCoverageInfo), DataType.pointer),
]
};

Expand Down

0 comments on commit 7a104d0

Please sign in to comment.