public void TestStackTraceCreation_AndroidMixModeCallStack_ValidStackTraceObject()
        {
            var stackTrace          = ConvertStackTraceToString(_mixModeCallStack);
            var exception           = new BacktraceUnhandledException(string.Empty, stackTrace);
            var backtraceStackTrace = new BacktraceStackTrace(exception);
            //skip first frame
            int startIndex = exception.Header ? 1 : 0;

            for (int i = startIndex; i < _mixModeCallStack.Count; i++)
            {
                var mixModeCallStack    = _mixModeCallStack.ElementAt(i);
                var backtraceStackFrame = backtraceStackTrace.StackFrames[i - startIndex];
                if (!string.IsNullOrEmpty(mixModeCallStack.Custom))
                {
                    Assert.AreEqual(mixModeCallStack.FunctionName, backtraceStackFrame.FunctionName);
                }
                else
                {
                    Assert.AreEqual(mixModeCallStack.FunctionName, backtraceStackFrame.FunctionName);
                    Assert.AreEqual(mixModeCallStack.Line, backtraceStackFrame.Line);
                    Assert.AreEqual(mixModeCallStack.FileName, backtraceStackFrame.FileName);
                    Assert.AreEqual(mixModeCallStack.Library, backtraceStackFrame.Library);
                }
            }
        }
        public IEnumerator TestReportFilter_ShouldPreventFromSendingUnhandledException_ClientNotSendingData()
        {
            var eventCalled = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                eventCalled = true;
                return(null);
            };
            BacktraceClient.SkipReport = (ReportFilterType type, Exception e, string message) =>
            {
                eventCalled = true;
                return(false);
            };

            // in this situation to learn if we were able to continue processing report
            // we should check if before send event or reportFilter event was called
            BacktraceClient.Configuration.ReportFilterType = ReportFilterType.UnhandledException;
            var exception = new BacktraceUnhandledException(string.Empty, string.Empty);

            BacktraceClient.Send(exception);
            yield return(new WaitForEndOfFrame());

            Assert.IsFalse(eventCalled);

            yield return(null);
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldUseReportFingerprint_ReportFingerprintInAttributes()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = true;
            BacktraceClient.Refresh();

            // exception without stack trace might happened when exception occured because of
            // invalid game object setting or via weird crash
            // exception below has empty exception stack trace
            var          exception           = new BacktraceUnhandledException("00:00:00 00/00/00 Unhandled exception", string.Empty);
            var          report              = new BacktraceReport(exception);
            const string expectedFingerprint = "foo-bar";

            report.Fingerprint = expectedFingerprint;

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                eventFired = true;
                Assert.IsNotNull(data.Attributes.Attributes["_mod_fingerprint"]);
                Assert.AreEqual(expectedFingerprint, data.Attributes.Attributes["_mod_fingerprint"]);
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };
            BacktraceClient.Send(report);
            yield return(new WaitForEndOfFrame());

            Assert.IsTrue(eventFired);
        }
        public IEnumerator TestReportFilter_ShouldPreventFromSendingDifferentTypeOfExceptions_ClientNotSendingData()
        {
            var reportFilterCalled = false;
            var beforeSendCalled   = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                beforeSendCalled = true;
                return(null);
            };
            BacktraceClient.SkipReport = (ReportFilterType type, Exception e, string message) =>
            {
                reportFilterCalled = true;
                return(false);
            };

            // in this situation to learn if we were able to continue processing report
            // we should check if before send event or reportFilter event was called
            BacktraceClient.Configuration.ReportFilterType = ReportFilterType.Exception & ReportFilterType.UnhandledException;
            var exception = new BacktraceUnhandledException("ANRException: Blocked thread detected", string.Empty);

            BacktraceClient.Send(exception);
            BacktraceClient.Send(new Exception("foo bar"));

            yield return(new WaitForEndOfFrame());

            Assert.IsTrue(reportFilterCalled);
            Assert.IsTrue(beforeSendCalled);
            yield return(null);
        }
        public IEnumerator TestBeforeSendEvent_UpdateReportAttributesForUnhandledException_ShouldUpdateReportAttributes()
        {
            var clientConfiguration = GetValidClientConfiguration();

            BacktraceClient.Configuration = clientConfiguration;
            BacktraceClient.Refresh();
            var attributeName  = "foo";
            var attributeValue = "bar";

            BacktraceClient.BeforeSend = (BacktraceData d) =>
            {
                d.Attributes.Attributes[attributeName] = attributeValue;
                return(d);
            };
            BacktraceClient.RequestHandler = (string url, BacktraceData d) =>
            {
                Assert.AreEqual(d.Attributes.Attributes[attributeName], attributeValue);
                return(new BacktraceResult
                {
                    Status = BacktraceResultStatus.Ok
                });
            };

            var unhandledException = new BacktraceUnhandledException("foo", string.Empty);

            BacktraceClient.Send(unhandledException);
            yield return(null);
        }
Ejemplo n.º 6
0
        public void TestStackTraceCreation_UnityEngineException_ValidStackTraceObject()
        {
            var source = new List <List <SampleStackFrame> >()
            {
                _simpleStack, _advancedStack
            };

            foreach (var data in source)
            {
                var stackTrace = ConvertStackTraceToString(data);

                string message             = "message";
                var    exception           = new BacktraceUnhandledException(message, stackTrace);
                var    backtraceStackTrace = new BacktraceStackTrace(exception);

                //skip first frame
                int startIndex = exception.Header ? 1 : 0;
                for (int i = startIndex; i < backtraceStackTrace.StackFrames.Count; i++)
                {
                    var backtraceStackFrame = backtraceStackTrace.StackFrames[i - startIndex];
                    var realStackFrame      = data[i];
                    Assert.AreEqual(realStackFrame.FunctionName, backtraceStackFrame.FunctionName);
                    Assert.AreEqual(realStackFrame.Line, backtraceStackFrame.Line);
                    Assert.AreEqual(realStackFrame.Library, backtraceStackFrame.Library);
                }
                // -1 because we include header in stack trace
                Assert.AreEqual(data.Count - startIndex, backtraceStackTrace.StackFrames.Count);
            }
        }
        public IEnumerator TestStackTraceCreation_UnityEngineException_ValidStackTraceObject()
        {
            var source = new List <List <SampleStackFrame> >()
            {
                _simpleStack, _advancedStack
            };

            foreach (var data in source)
            {
                var stringBuilder = new StringBuilder();
                foreach (var stackFrame in data)
                {
                    stringBuilder.Append(stackFrame.ToStackFrameString());
                }
                var stackTrace = stringBuilder.ToString();

                string message             = "message";
                var    exception           = new BacktraceUnhandledException(message, stackTrace);
                var    backtraceStackTrace = new BacktraceStackTrace(exception);

                //skip first frame
                int startIndex = exception.Header ? 1 : 0;
                for (int i = startIndex; i < backtraceStackTrace.StackFrames.Count; i++)
                {
                    var backtraceStackFrame = backtraceStackTrace.StackFrames[i - startIndex];
                    var realStackFrame      = data[i];
                    Assert.AreEqual(realStackFrame.Method, backtraceStackFrame.FunctionName);
                    Assert.AreEqual(realStackFrame.LineNumber, backtraceStackFrame.Line);
                    Assert.AreEqual(realStackFrame.Path, backtraceStackFrame.Library);
                }
                // -1 because we include header in stack trace
                Assert.AreEqual(data.Count - startIndex, backtraceStackTrace.StackFrames.Count);
            }
            yield return(null);
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldntGenerateFingerprintForDisabledOption_FingerprintDoesntExist()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = false;
            BacktraceClient.Refresh();

            // exception without stack trace might happened when exception occured because of
            // invalid game object setting or via weird crash
            // exception below has empty exception stack trace
            var exception = new BacktraceUnhandledException("00:00:00 00/00/00 Unhandled exception", string.Empty);
            var report    = new BacktraceReport(exception);

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                Assert.IsFalse(data.Attributes.Attributes.ContainsKey("_mod_fingerprint"));
                eventFired = true;
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };

            yield return(BacktraceClient.StartCoroutine(CallBacktraceClientAndWait(report)));


            Assert.IsTrue(eventFired);
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldGenerateFingerprintAndShouldntRemoveAnyLetter_ShouldIncludeFingerprintInBacktraceReport()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = true;
            BacktraceClient.Refresh();

            var normalizedMessage = "Unhandledexception";
            var exception         = new BacktraceUnhandledException(normalizedMessage, string.Empty);
            var report            = new BacktraceReport(exception);

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                const string modFingerprintKey = "_mod_fingerprint";
                Assert.IsTrue(data.Attributes.Attributes.ContainsKey(modFingerprintKey));
                Assert.IsNotNull(data.Attributes.Attributes[modFingerprintKey]);
                Assert.AreEqual(normalizedMessage.GetSha(), data.Attributes.Attributes[modFingerprintKey]);
                // prevent backtrace data from sending to Backtrace.
                eventFired = true;
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };

            yield return(BacktraceClient.StartCoroutine(CallBacktraceClientAndWait(report)));

            Assert.IsTrue(eventFired);
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldGenerateFingerprintForExceptionReportWithoutStackTrace_ShouldIncludeFingerprintInBacktraceReport()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = true;
            BacktraceClient.Refresh();

            // exception without stack trace might happened when exception occured because of
            // invalid game object setting or via weird crash
            // exception below has empty exception stack trace
            var exception = new BacktraceUnhandledException("00:00:00 00/00/00 Unhandled exception", string.Empty);
            var expectedNormalizedMessage = "Unhandledexception";
            var report = new BacktraceReport(exception);

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                Assert.IsNotNull(data.Attributes.Attributes["_mod_fingerprint"]);
                Assert.AreEqual(expectedNormalizedMessage.GetSha(), data.Attributes.Attributes["_mod_fingerprint"]);
                eventFired = true;
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };

            yield return(BacktraceClient.StartCoroutine(CallBacktraceClientAndWait(report)));


            Assert.IsTrue(eventFired);
        }
Ejemplo n.º 11
0
        public void ExceptionStackTrace_ShouldGenerateEnvStackTraceIfExStackTraceIsEmpty_ExceptionShouldHaveExceptionStackTrace()
        {
            var error = new BacktraceUnhandledException("error message", string.Empty);

            Assert.AreEqual(error.StackTrace, string.Empty);
            Assert.IsTrue(error.StackFrames.Any());
        }
Ejemplo n.º 12
0
        public void JITStackTrace_ShouldParseCorrectlyJITStackTrace_StackTraceObjectIsGeneratedCorrectly()
        {
            var simpleFunctionName = "GetStacktrace";
            var functionNameWithWrappedManagedPrefix = "UnityEngine.DebugLogHandler:Internal_Log";
            var functioNamewithMonoJitCodePrefix     = "ServerGameManager:SendInitialiseNetObjectToClient";
            var jitStackTrace = string.Format(@"#0 {0} (int)
                 #1 DebugStringToFile(DebugStringToFileData const&)
                 #2 DebugLogHandler_CUSTOM_Internal_Log(LogType, LogOption, ScriptingBackendNativeStringPtrOpaque*, ScriptingBackendNativeObjectPtrOpaque*)
                 #3  (Mono JIT Code) (wrapper managed-to-native) {1} (UnityEngine.LogType,UnityEngine.LogOption,string,UnityEngine.Object)
                 #4  (Mono JIT Code) {2} (FG.Common.GameConnection,FG.Common.NetObjectSpawnData)
                 #5  (Mono JIT Code) ServerGameManager:SpawnAlreadySpawnedObjectsForClient (FG.Common.GameConnection)
                 #6  (Mono JIT Code) ServerGameManager:ProcessLevelLoaded (FG.Common.GameConnection)
                 #7  (Mono JIT Code) ServerGameManager:ProcessClientReady (FG.Common.GameConnection,FG.Common.PlayerReadinessState)
                 #8  (Mono JIT Code) FG.Common.UnityNetworkMessageHandler:HandleAndFreeInboundGameMessage (FG.Common.MessageEnvelope)
                 #9  (Mono JIT Code) FG.Common.UnityNetworkMessageHandler:PeekAndHandleMessage (UnityEngine.Networking.NetworkMessage,FG.Common.GameConnection)
                 #10  (Mono JIT Code) FG.Common.FG_UnityInternetNetworkManager:ServerHandleMessageReceived (UnityEngine.Networking.NetworkMessage)",
                                              simpleFunctionName, functionNameWithWrappedManagedPrefix, functioNamewithMonoJitCodePrefix);


            var backtraceUnhandledException = new BacktraceUnhandledException("foo", jitStackTrace);

            Assert.AreEqual(11, backtraceUnhandledException.StackFrames.Count);
            Assert.AreEqual(backtraceUnhandledException.StackFrames[0].FunctionName, simpleFunctionName);
            Assert.AreEqual(backtraceUnhandledException.StackFrames[3].FunctionName, functionNameWithWrappedManagedPrefix);
            Assert.AreEqual(backtraceUnhandledException.StackFrames[4].FunctionName, functioNamewithMonoJitCodePrefix);
        }
Ejemplo n.º 13
0
        public void ExceptionStackTrace_ShouldGenerateEnvStackTraceIfExStackTraceIsInvalid_ExceptionShouldHaveExceptionStackTrace()
        {
            var invalidStackTrace = "--";
            var error             = new BacktraceUnhandledException("error message", invalidStackTrace);

            Assert.AreEqual(error.StackTrace, invalidStackTrace);
            Assert.IsTrue(error.StackFrames.Any());
        }
Ejemplo n.º 14
0
        public void ExceptionStackTrace_NoStackTraceAvailable_ExceptionShouldHaveEnvironmentStackTrace()
        {
            var message = "message";
            // in this case BacktraceUnhandledException should generate environment stack trace
            var unhandledExceptionReport = new BacktraceUnhandledException(message, string.Empty);

            Assert.IsNotEmpty(unhandledExceptionReport.StackFrames);
        }
Ejemplo n.º 15
0
        public void TestClassifierSetter_SetAClassifierBasedOnErrorMessageNotStackFrames_ShoudlSetClassifier()
        {
            var stackTrace = ConvertStackTraceToString(_simpleStack);
            // should guess classifier based on first stack frame
            string message   = _mixModeClassifier;
            var    exception = new BacktraceUnhandledException(message, stackTrace);

            Assert.AreEqual(_mixModeClassifier, exception.Classifier);
        }
Ejemplo n.º 16
0
        public void TestClassifierSetter_DontSetClassifierIfClassifierIsNotAvailable_ShouldUseDefaultClassifier()
        {
            var stackTrace = ConvertStackTraceToString(_simpleStack);
            // should guess classifier based on first stack frame
            string message   = string.Empty;
            var    exception = new BacktraceUnhandledException(message, stackTrace);

            Assert.AreEqual("BacktraceUnhandledException", exception.Classifier);
        }
Ejemplo n.º 17
0
        public void TestClassifierSetter_SetAdvancedIl2CPPClassifier_ShoudlSetClassifier()
        {
            var stackTrace = ConvertStackTraceToString(_advancedStack);
            // should guess classifier based on first stack frame
            string message   = string.Empty;
            var    exception = new BacktraceUnhandledException(message, stackTrace);

            Assert.AreEqual(_advancedStackTraceClassifier, exception.Classifier);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// ANR Detection event. This method will be replaced by Backtrace-Android soon native API.
        /// </summary>
        /// <param name="stackTrace">Main thread stack trace</param>
        internal void OnAnrDetected(string stackTrace)
        {
            const string anrMessage = "ANRException: Blocked thread detected";

            _backtraceLogManager.Enqueue(new BacktraceUnityMessage(anrMessage, stackTrace, LogType.Error));
            var hang = new BacktraceUnhandledException(anrMessage, stackTrace);

            SendUnhandledException(hang);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Catch Unity logger data and create Backtrace reports for log type that represents exception or error
        /// </summary>
        /// <param name="message">Log message</param>
        /// <param name="stackTrace">Log stack trace</param>
        /// <param name="type">log type</param>
        internal void HandleUnityMessage(string message, string stackTrace, LogType type)
        {
            if (!Enabled || !Configuration.HandleUnhandledExceptions)
            {
                return;
            }
            if (string.IsNullOrEmpty(message) || (type != LogType.Error && type != LogType.Exception))
            {
                return;
            }

            if (Configuration.ReportFilterType.HasFlag(ReportFilterType.Error) && type == LogType.Error)
            {
                return;
            }

            BacktraceUnhandledException exception = null;
            var invokeSkipApi = true;

            // detect sampling flow for LogType.Error + filter LogType.Error if client prefer to ignore them.
            if (type == LogType.Error)
            {
                if (Configuration.ReportFilterType.HasFlag(ReportFilterType.Error))
                {
                    return;
                }
                if (SamplingShouldSkip())
                {
                    if (SkipReport != null)
                    {
                        exception = new BacktraceUnhandledException(message, stackTrace)
                        {
                            Type = type
                        };
                        if (ShouldSkipReport(ReportFilterType.Error, exception, string.Empty))
                        {
                            return;
                        }
                        invokeSkipApi = false;
                    }
                    else
                    {
                        return;
                    }
                }
            }

            if (exception == null)
            {
                exception = new BacktraceUnhandledException(message, stackTrace)
                {
                    Type = type
                };
            }

            SendUnhandledException(exception, invokeSkipApi);
        }
Ejemplo n.º 20
0
        public void TestClassifierSetter_SetMixModeCallStackWithJavaClassifier_ShoudlSetJavaClassifier()
        {
            var stackTrace = ConvertStackTraceToString(_mixModeCallStack);
            // should guess classifier based on first stack frame
            string message   = string.Empty;
            var    exception = new BacktraceUnhandledException(message, stackTrace);

            Assert.AreEqual(_mixModeClassifier, exception.Classifier);
        }
 private void HandleException(string condition, string stackTrace, LogType type)
 {
     if (type == LogType.Exception || type == LogType.Error)
     {
         var exception = new BacktraceUnhandledException(condition, stackTrace);
         var report    = new BacktraceReport(exception);
         Send(report);
     }
 }
Ejemplo n.º 22
0
        public void TestClassifierSetter_SetCorrectReportClassifier_ShoudlSetReportClassifier()
        {
            var stackTrace = ConvertStackTraceToString(_simpleStack);
            // should guess classifier based on first stack frame
            string message   = _mixModeClassifier;
            var    exception = new BacktraceUnhandledException(message, stackTrace);
            var    report    = new BacktraceReport(exception);

            Assert.AreEqual(_mixModeClassifier, report.Classifier);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Catch Unity logger data and create Backtrace reports for log type that represents exception or error
        /// </summary>
        /// <param name="message">Log message</param>
        /// <param name="stackTrace">Log stack trace</param>
        /// <param name="type">log type</param>
        internal void HandleUnityMessage(string message, string stackTrace, LogType type)
        {
            var unityMessage = new BacktraceUnityMessage(message, stackTrace, type);

            _backtraceLogManager.Enqueue(unityMessage);
            if (Configuration.HandleUnhandledExceptions && unityMessage.IsUnhandledException())
            {
                var exception = new BacktraceUnhandledException(unityMessage.Message, unityMessage.StackTrace);
                SendUnhandledException(exception);
            }
        }
        public void TestReportClassifier_ShouldSetErrorClassifierBasedOnUnhandledExceptionMessage_SetCorrectExceptionReportClassifier()
        {
            string expectedExceptionName = "ArgumentException";
            var    exception             = new BacktraceUnhandledException(expectedExceptionName, string.Empty);
            var    report = new BacktraceReport(
                exception: exception,
                attributes: reportAttributes,
                attachmentPaths: attachemnts);

            Assert.AreEqual(expectedExceptionName, report.Classifier);
        }
Ejemplo n.º 25
0
 private void SendUnhandledException(BacktraceUnhandledException exception, bool invokeSkipApi = true)
 {
     if (OnUnhandledApplicationException != null)
     {
         OnUnhandledApplicationException.Invoke(exception);
     }
     if (ShouldSendReport(exception, null, null, invokeSkipApi))
     {
         SendReport(new BacktraceReport(exception));
     }
 }
        public void MissingStackTraceReport_GenerateNotFaultingStackTrace_ReportShouldntHaveFaultingThread()
        {
            var message = "message";
            // in this case BacktraceUnhandledException should generate environment stack trace
            var unhandledException = new BacktraceUnhandledException(message, string.Empty);

            Assert.IsNotEmpty(unhandledException.StackFrames);
            var report = new BacktraceReport(unhandledException);
            var data   = new BacktraceData(report, null);

            Assert.IsFalse(data.ThreadData.ThreadInformations.First().Value.Fault);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// ANR Detection event. This method will be replaced by Backtrace-Android soon native API.
        /// </summary>
        /// <param name="stackTrace">Main thread stack trace</param>
        internal void OnAnrDetected(string stackTrace)
        {
            if (!Enabled)
            {
                Debug.LogWarning("Please enable BacktraceClient first.");
                return;
            }
            const string anrMessage = "ANRException: Blocked thread detected";

            _backtraceLogManager.Enqueue(new BacktraceUnityMessage(anrMessage, stackTrace, LogType.Error));
            var hang = new BacktraceUnhandledException(anrMessage, stackTrace);

            SendUnhandledException(hang);
        }
Ejemplo n.º 28
0
        public void ExceptionStackTrace_StackTraceAvailable_ExceptionShouldHaveExceptionStackTrace()
        {
            var message       = "message";
            var stringBuilder = new StringBuilder();

            foreach (var stackFrame in _simpleStack)
            {
                stringBuilder.Append(stackFrame.ToStackFrameString());
            }
            var stackTrace = stringBuilder.ToString();
            var error      = new BacktraceUnhandledException(message, stackTrace);

            Assert.AreEqual(_simpleStack.Count, error.StackFrames.Count);
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Catch Unity logger data and create Backtrace reports for log type that represents exception or error
        /// </summary>
        /// <param name="message">Log message</param>
        /// <param name="stackTrace">Log stack trace</param>
        /// <param name="type">log type</param>
        private void HandleException(string message, string stackTrace, LogType type)
        {
            if ((type == LogType.Exception || type == LogType.Error) &&
                (!string.IsNullOrEmpty(message) && !message.StartsWith("[Backtrace]::")))
            {
                var exception = new BacktraceUnhandledException(message, stackTrace);

                if (OnUnhandledApplicationException != null)
                {
                    OnUnhandledApplicationException.Invoke(exception);
                }

                Send(exception);
            }
        }
Ejemplo n.º 30
0
        public void TestStackTraceCreation_AndroidException_ValidStackTraceObject()
        {
            var stackTrace          = ConvertStackTraceToString(_anrStackTrace);
            var exception           = new BacktraceUnhandledException(string.Empty, stackTrace);
            var backtraceStackTrace = new BacktraceStackTrace(exception);

            for (int i = 0; i < _anrStackTrace.Count; i++)
            {
                var anrStackFrame       = _anrStackTrace.ElementAt(i);
                var backtraceStackFrame = backtraceStackTrace.StackFrames[i];
                Assert.AreEqual(anrStackFrame.FunctionName, backtraceStackFrame.FunctionName);
                Assert.AreEqual(anrStackFrame.Line, backtraceStackFrame.Line);
                Assert.AreEqual(anrStackFrame.Library, backtraceStackFrame.Library);
            }
        }