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); }
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); }
public void ExceptionStackTrace_ShouldGenerateEnvStackTraceIfExStackTraceIsEmpty_ExceptionShouldHaveExceptionStackTrace() { var error = new BacktraceUnhandledException("error message", string.Empty); Assert.AreEqual(error.StackTrace, string.Empty); Assert.IsTrue(error.StackFrames.Any()); }
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); }
public void ExceptionStackTrace_ShouldGenerateEnvStackTraceIfExStackTraceIsInvalid_ExceptionShouldHaveExceptionStackTrace() { var invalidStackTrace = "--"; var error = new BacktraceUnhandledException("error message", invalidStackTrace); Assert.AreEqual(error.StackTrace, invalidStackTrace); Assert.IsTrue(error.StackFrames.Any()); }
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); }
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); }
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); }
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); }
/// <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); }
/// <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); }
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); } }
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); }
/// <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); }
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); }
/// <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); }
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); }
/// <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); } }
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); } }