Repository: dotnet/runtime
File: src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs (C#)

Code before:
                @"V1Methods.*Test0",
                @"V2Methods\.Quux\(\).*Quux.*\.cs:line 6"
            }},
            { "Quuux", new[] {
                @"Exception from Quuux2",
                @"V2Methods\.Quuux2\(\).*Quuux2.*\.cs:line 4",
                @"V2Methods\.Quuux\(\).*Quuux.*\.cs:line [35]" // if yield finishes before Task is awaited, line 3 else line 5. Either is ok.
            }},
            {"Bux", new[] {
                @"Exception from Baz method.",
                @"V2Methods\.Baz\(\).*Baz.*\.cs:line 4",
                @"V2Methods\.Bux\(\).*Bux.*\.cs:line 6"
            }},
        };

        public static IEnumerable<object[]> Ctor_Async_TestData()
        {
            yield return new object[] { () => V2Methods.Foo(), MethodExceptionStrings["Foo"] };
            yield return new object[] { () => V2Methods.Bar(3), MethodExceptionStrings["Bar"] };
            yield return new object[] { () => V2Methods.Quux(), MethodExceptionStrings["Quux"] };
            yield return new object[] { () => V2Methods.Quuux(), MethodExceptionStrings["Quuux"] };
            yield return new object[] { () => V2Methods.Bux(), MethodExceptionStrings["Bux"] };
        }

        [ActiveIssue("https://github.com/dotnet/runtime/issues/123979", typeof(PlatformDetection), nameof(PlatformDetection.IsArmProcess))]
        [ActiveIssue("https://github.com/dotnet/runtime/issues/124015", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process))]
        [ActiveIssue("https://github.com/dotnet/runtime/issues/124044", TestPlatforms.iOS | TestPlatforms.tvOS)]
        [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsRuntimeAsyncSupported))]
        [MemberData(nameof(Ctor_Async_TestData))]
        [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
        public async Task ToString_Async(Func<Task> asyncMethod, string[] expectedPatterns)
        {
            Exception? caughtException = null;
            try
            {
                await asyncMethod();
            }
            catch (Exception ex)
            {
                caughtException = ex;
            }

            Assert.NotNull(caughtException);
            string exceptionText = caughtException.ToString();
            int startIndex = 0;
            foreach (string pattern in expectedPatterns)
            {
                Regex regex = new(pattern, RegexOptions.None, TimeSpan.FromSeconds(10));
                Match match = regex.Match(exceptionText, startIndex);
                Assert.True(match.Success, $"Could not find expected pattern '{pattern}' in exception text:\n{exceptionText} starting at index {startIndex}.");
                startIndex = match.Index + match.Length;

Review comment (suggestion):
BTW: Why are these tests running on iOS? I would expect them to be disabled by this `IsArm64Process` condition

Code after:
                @"V1Methods.*Test0",
                @"V2Methods\.Quux\(\).*Quux.*\.cs:line 6"
            }},
            { "Quuux", new[] {
                @"Exception from Quuux2",
                @"V2Methods\.Quuux2\(\).*Quuux2.*\.cs:line 4",
                @"V2Methods\.Quuux\(\).*Quuux.*\.cs:line [35]" // if yield finishes before Task is awaited, line 3 else line 5. Either is ok.
            }},
            {"Bux", new[] {
                @"Exception from Baz method.",
                @"V2Methods\.Baz\(\).*Baz.*\.cs:line 4",
                @"V2Methods\.Bux\(\).*Bux.*\.cs:line 6"
            }},
        };

        public static IEnumerable<object[]> Ctor_Async_TestData()
        {
            yield return new object[] { () => V2Methods.Foo(), MethodExceptionStrings["Foo"] };
            yield return new object[] { () => V2Methods.Bar(3), MethodExceptionStrings["Bar"] };
            yield return new object[] { () => V2Methods.Quux(), MethodExceptionStrings["Quux"] };
            yield return new object[] { () => V2Methods.Quuux(), MethodExceptionStrings["Quuux"] };
            yield return new object[] { () => V2Methods.Bux(), MethodExceptionStrings["Bux"] };
        }

        [ActiveIssue("https://github.com/dotnet/runtime/issues/123979", typeof(PlatformDetection), nameof(PlatformDetection.IsArmProcess))]
        [ActiveIssue("https://github.com/dotnet/runtime/issues/124015", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process))]
        [ActiveIssue("https://github.com/dotnet/runtime/issues/124044", typeof(PlatformDetection), nameof(PlatformDetection.IsCoreClrInterpreter))]
        [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsRuntimeAsyncSupported))]
        [MemberData(nameof(Ctor_Async_TestData))]
        [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
        public async Task ToString_Async(Func<Task> asyncMethod, string[] expectedPatterns)
        {
            Exception? caughtException = null;
            try
            {
                await asyncMethod();
            }
            catch (Exception ex)
            {
                caughtException = ex;
            }

            Assert.NotNull(caughtException);
            string exceptionText = caughtException.ToString();
            int startIndex = 0;
            foreach (string pattern in expectedPatterns)
            {
                Regex regex = new(pattern, RegexOptions.None, TimeSpan.FromSeconds(10));
                Match match = regex.Match(exceptionText, startIndex);
                Assert.True(match.Success, $"Could not find expected pattern '{pattern}' in exception text:\n{exceptionText} starting at index {startIndex}.");
                startIndex = match.Index + match.Length;