Ejemplo n.º 1
0
 public ProgramPairResults(
     ProgramResult debugResult, ProgramResult releaseResult,
     ChecksumSite debugFirstUnmatch, ChecksumSite releaseFirstUnmatch)
 {
     DebugResult         = debugResult;
     ReleaseResult       = releaseResult;
     DebugFirstUnmatch   = debugFirstUnmatch;
     ReleaseFirstUnmatch = releaseFirstUnmatch;
 }
Ejemplo n.º 2
0
    private static ProgramPairResults RunPairAsync(AssemblyLoadContext alc, ProgramPair pair)
    {
        ProgramResult debugResult   = RunAndGetResultAsync(pair.Debug);
        ProgramResult releaseResult = RunAndGetResultAsync(pair.Release);
        ChecksumSite  unmatch1      = null;
        ChecksumSite  unmatch2      = null;

        if (debugResult.Checksum != releaseResult.Checksum && pair.TrackOutput)
        {
            int index;
            int count = Math.Min(debugResult.ChecksumSites.Count, releaseResult.ChecksumSites.Count);
            for (index = 0; index < count; index++)
            {
                ChecksumSite val1 = debugResult.ChecksumSites[index];
                ChecksumSite val2 = releaseResult.ChecksumSites[index];
                if (val1 != val2)
                {
                    break;
                }
            }

            if (index < debugResult.ChecksumSites.Count)
            {
                unmatch1 = debugResult.ChecksumSites[index];
            }
            if (index < releaseResult.ChecksumSites.Count)
            {
                unmatch2 = releaseResult.ChecksumSites[index];
            }
        }

        return(new ProgramPairResults(debugResult, releaseResult, unmatch1, unmatch2));

        ProgramResult RunAndGetResultAsync(byte[] bytes)
        {
            Assembly          asm            = alc.LoadFromStream(new MemoryStream(bytes));
            MethodInfo        mainMethodInfo = asm.GetType("Program").GetMethod("Main");
            Action <IRuntime> entryPoint     = (Action <IRuntime>)Delegate.CreateDelegate(typeof(Action <IRuntime>), mainMethodInfo);
            var runtime = new Runtime();

            List <ChecksumSite> TakeChecksumSites()
            {
                // A reference to the runtime stays in the loaded assembly and there may be a lot of checksum sites
                // so during reduction this can use a lot of memory.
                List <ChecksumSite> checksumSites = runtime.ChecksumSites;

                runtime.ChecksumSites = null;
                return(checksumSites);
            }

            if (pair.TrackOutput)
            {
                runtime.ChecksumSites = new List <ChecksumSite>();
            }

            int threadID = Environment.CurrentManagedThreadId;
            List <Exception> exceptions = null;

            void FirstChanceExceptionHandler(object sender, FirstChanceExceptionEventArgs args)
            {
                if (Environment.CurrentManagedThreadId == threadID)
                {
                    (exceptions ??= new List <Exception>()).Add(args.Exception);
                }
            }

            AppDomain.CurrentDomain.FirstChanceException += FirstChanceExceptionHandler;
            try
            {
                entryPoint(runtime);
            }
            catch
            {
                // We consider the innermost exception the root cause and only report it.
                // Otherwise we may be confusing the viewer about what the problem is.
                // Consider for example (adapted from a real example):
                // try
                // {
                //   value = -1;
                //   FunctionThatJitAssertsInDebug();
                //   value = 1;
                // }
                // finally
                // {
                //   int.MinValue / value;
                // }
                // We are interested in the JIT assert that was hit, and not the OverflowException
                // thrown because value = 1 did not get to run.
                Exception ex = exceptions[0];

                if (ex is InvalidProgramException && ex.Message.Contains("JIT assert failed"))
                {
                    return(new ProgramResult
                    {
                        Kind = ProgramResultKind.HitsJitAssert,
                        Checksum = runtime.FinishHashCode(),
                        ChecksumSites = TakeChecksumSites(),
                        JitAssertError = ex.Message,
                    });
                }

                return(new ProgramResult
                {
                    Kind = ProgramResultKind.ThrowsException,
                    Checksum = runtime.FinishHashCode(),
                    ChecksumSites = TakeChecksumSites(),
                    ExceptionType = ex.GetType().FullName,
                    ExceptionText = ex.ToString(),
                    ExceptionStackTrace = ex.StackTrace,
                });
            }
            finally
            {
                AppDomain.CurrentDomain.FirstChanceException -= FirstChanceExceptionHandler;
            }

            return(new ProgramResult
            {
                Kind = ProgramResultKind.RunsSuccessfully,
                Checksum = runtime.FinishHashCode(),
                ChecksumSites = TakeChecksumSites(),
            });
        }
    }