Skip to content

Reenable Linux tests that were disabled #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions src/tests/JIT/Directed/debugging/debuginfo/tester.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
extern alias tests_d;
extern alias tests_r;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.Diagnostics.Tools.RuntimeClient;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Parsers.Clr;
using Tracing.Tests.Common;
using DebugInfoMethodsD = tests_d::DebugInfoMethods;
using DebugInfoMethodsR = tests_r::DebugInfoMethods;

public unsafe class DebugInfoTest
{
public static unsafe int Main()
{
var keywords =
ClrTraceEventParser.Keywords.Jit | ClrTraceEventParser.Keywords.JittedMethodILToNativeMap;

var dotnetRuntimeProvider = new List<Provider>
{
new Provider("Microsoft-Windows-DotNETRuntime", eventLevel: EventLevel.Verbose, keywords: (ulong)keywords)
};

var config = new SessionConfiguration(1024, EventPipeSerializationFormat.NetTrace, dotnetRuntimeProvider);

return
IpcTraceTest.RunAndValidateEventCounts(
new Dictionary<string, ExpectedEventCount>(),
JitMethods,
config,
ValidateMappings);
}

private static void JitMethods()
{
ProcessType(typeof(DebugInfoMethodsD));
ProcessType(typeof(DebugInfoMethodsR));
}

private static void ProcessType(Type t)
{
foreach (MethodInfo mi in t.GetMethods())
{
if (mi.GetCustomAttribute<ExpectedILMappings>() != null)
{
RuntimeHelpers.PrepareMethod(mi.MethodHandle);
}
}
}

private static Func<int> ValidateMappings(EventPipeEventSource source)
{
List<(long MethodID, OptimizationTier Tier, (int ILOffset, int NativeOffset)[] Mappings)> methodsWithMappings = new();
Dictionary<long, OptimizationTier> methodTier = new();

source.Clr.MethodLoad += e => methodTier[e.MethodID] = e.OptimizationTier;
source.Clr.MethodLoadVerbose += e => methodTier[e.MethodID] = e.OptimizationTier;
source.Clr.MethodILToNativeMap += e =>
{
if (e.MethodID == 0)
return;

var mappings = new (int, int)[e.CountOfMapEntries];
for (int i = 0; i < mappings.Length; i++)
mappings[i] = (e.ILOffset(i), e.NativeOffset(i));

if (!methodTier.TryGetValue(e.MethodID, out OptimizationTier tier))
tier = OptimizationTier.Unknown;

methodsWithMappings.Add((e.MethodID, tier, mappings));
};

return () =>
{
int result = 100;
foreach ((long methodID, OptimizationTier tier, (int ILOffset, int NativeOffset)[] mappings) in methodsWithMappings)
{
MethodBase meth = s_getMethodBaseByHandle(null, (IntPtr)(void*)methodID);
ExpectedILMappings attrib = meth.GetCustomAttribute<ExpectedILMappings>();
if (attrib == null)
{
continue;
}

string name = $"[{meth.DeclaringType.Assembly.GetName().Name}]{meth.DeclaringType.FullName}.{meth.Name}";

// If DebuggableAttribute is saying that the assembly must be debuggable, then verify debug mappings.
// Otherwise verify release mappings.
// This may seem a little strange since we do not use the tier at all -- however, we expect debug
// to never tier and in release, we expect the release mappings to be the "least common denominator",
// i.e. tier0 and tier1 mappings should both be a superset.
// Note that tier0 and MinOptJitted differs in mappings generated exactly due to DebuggableAttribute.
DebuggableAttribute debuggableAttrib = meth.DeclaringType.Assembly.GetCustomAttribute<DebuggableAttribute>();
bool debuggableMappings = debuggableAttrib != null && debuggableAttrib.IsJITOptimizerDisabled;

Console.WriteLine("{0}: Validate mappings for {1} codegen (tier: {2})", name, debuggableMappings ? "debuggable" : "optimized", tier);

int[] expected = debuggableMappings ? attrib.Debug : attrib.Opts;
if (expected == null)
{
continue;
}

if (!ValidateSingle(expected, mappings))
{
Console.WriteLine(" Validation failed: expected mappings at IL offsets {0}", string.Join(", ", expected.Select(il => $"{il:x3}")));
Console.WriteLine(" Actual (IL <-> native):");
foreach ((int ilOffset, int nativeOffset) in mappings)
{
string ilOffsetName = Enum.IsDefined((SpecialILOffset)ilOffset) ? ((SpecialILOffset)ilOffset).ToString() : $"{ilOffset:x3}";
Console.WriteLine(" {0:x3} <-> {1:x3}", ilOffsetName, nativeOffset);
}

result = -1;
}
}

return result;
};
}

// Validate that all IL offsets we expected had mappings generated for them.
private static bool ValidateSingle(int[] expected, (int ILOffset, int NativeOffset)[] mappings)
{
return expected.All(il => mappings.Any(t => t.ILOffset == il));
}

private enum SpecialILOffset
{
NoMapping = -1,
Prolog = -2,
Epilog = -3,
}

static DebugInfoTest()
{
Type runtimeMethodHandleInternalType = typeof(RuntimeMethodHandle).Assembly.GetType("System.RuntimeMethodHandleInternal");
Type runtimeTypeType = typeof(RuntimeMethodHandle).Assembly.GetType("System.RuntimeType");
MethodInfo getMethodBaseMethod = runtimeTypeType.GetMethod("GetMethodBase", BindingFlags.NonPublic | BindingFlags.Static, new[] { runtimeTypeType, runtimeMethodHandleInternalType });
s_getMethodBaseByHandle = (delegate*<object, IntPtr, MethodBase>)getMethodBaseMethod.MethodHandle .GetFunctionPointer();
}

// Needed to go from MethodID -> MethodBase
private static readonly delegate*<object, IntPtr, MethodBase> s_getMethodBaseByHandle;
}
17 changes: 17 additions & 0 deletions src/tests/JIT/Directed/debugging/debuginfo/tester.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<DebugType>PdbOnly</DebugType>
<Optimize>True</Optimize>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<UnloadabilityIncompatible>true</UnloadabilityIncompatible>
<GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="tests_d.ilproj" Aliases="tests_d" />
<ProjectReference Include="tests_r.ilproj" Aliases="tests_r" />
<ProjectReference Include="attribute.csproj" />
<ProjectReference Include="../../../../tracing/eventpipe/common/common.csproj" />
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
108 changes: 108 additions & 0 deletions src/tests/tracing/eventpipe/gcdump/gcdump.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// 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.Diagnostics.Tracing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.Diagnostics.NETCore.Client;
using Microsoft.Diagnostics.Tools.RuntimeClient;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using Tracing.Tests.Common;
using Microsoft.Diagnostics.Tracing.Parsers.Clr;

namespace Tracing.Tests.EventSourceError
{
// Regression test for https://github.com/dotnet/runtime/issues/38639
public class GCDumpTest
{
private static int _bulkTypeCount = 0;
private static int _bulkNodeCount = 0;
private static int _bulkEdgeCount = 0;
private static int _bulkRootEdgeCount = 0;
private static int _bulkRootStaticVarCount = 0;

private static readonly ulong GC_HeapDump_Keyword = 0x100000UL;

public static int Main(string[] args)
{
// This test validates that if an EventSource generates an error
// during construction it gets emitted over EventPipe

List<Provider> providers = new List<Provider>
{
new Provider("Microsoft-Windows-DotNETRuntime", eventLevel: EventLevel.Verbose, keywords: (ulong)ClrTraceEventParser.Keywords.GCHeapSnapshot)
};

var configuration = new SessionConfiguration(circularBufferSizeMB: 1024, format: EventPipeSerializationFormat.NetTrace, providers: providers);
return IpcTraceTest.RunAndValidateEventCounts(_expectedEventCounts, _eventGeneratingAction, configuration, _DoesRundownContainMethodEvents);
}

private static Dictionary<string, ExpectedEventCount> _expectedEventCounts = new Dictionary<string, ExpectedEventCount>()
{
// This space intentionally left blank
};

private static Action _eventGeneratingAction = () =>
{
// This space intentionally left blank
};

private static Func<EventPipeEventSource, Func<int>> _DoesRundownContainMethodEvents = (source) =>
{
source.Clr.TypeBulkType += (GCBulkTypeTraceData data) =>
{
_bulkTypeCount += data.Count;
};

source.Clr.GCBulkNode += delegate (GCBulkNodeTraceData data)
{
_bulkNodeCount += data.Count;
};

source.Clr.GCBulkEdge += (GCBulkEdgeTraceData data) =>
{
_bulkEdgeCount += data.Count;
};

source.Clr.GCBulkRootEdge += (GCBulkRootEdgeTraceData data) =>
{
_bulkRootEdgeCount += data.Count;
};

source.Clr.GCBulkRootStaticVar += (GCBulkRootStaticVarTraceData data) =>
{
_bulkRootStaticVarCount += data.Count;
};

return () =>
{
// Hopefully it is low enough to be resilient to changes in the runtime
// and high enough to catch issues. There should be between hundreds and thousands
// for each, but the number is variable and the point of the test is to verify
// that we get any events at all.
if (_bulkTypeCount > 50
&& _bulkNodeCount > 50
&& _bulkEdgeCount > 50
&& _bulkRootEdgeCount > 50
&& _bulkRootStaticVarCount > 50)
{
return 100;
}


Console.WriteLine($"Test failed due to missing GC heap events.");
Console.WriteLine($"_bulkTypeCount = {_bulkTypeCount}");
Console.WriteLine($"_bulkNodeCount = {_bulkNodeCount}");
Console.WriteLine($"_bulkEdgeCount = {_bulkEdgeCount}");
Console.WriteLine($"_bulkRootEdgeCount = {_bulkRootEdgeCount}");
Console.WriteLine($"_bulkRootStaticVarCount = {_bulkRootStaticVarCount}");
return -1;
};
};
}
}
14 changes: 14 additions & 0 deletions src/tests/tracing/eventpipe/gcdump/gcdump.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
<OutputType>exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UnloadabilityIncompatible>true</UnloadabilityIncompatible>
<!-- This test provides no interesting scenarios for GCStress -->
<GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
<ProjectReference Include="../common/common.csproj" />
</ItemGroup>
</Project>