1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Text; 7 using System.Collections.Concurrent; 8 using System.Diagnostics; 9 using System.Threading; 10 11 namespace DPStressHarness 12 { 13 public class RecordedExceptions 14 { 15 // Reference wrapper around an integer which is used in order to make updating a little easier & more efficient 16 public class ExceptionCount 17 { 18 public int Count = 0; 19 } 20 21 private ConcurrentDictionary<string, ConcurrentDictionary<string, ExceptionCount>> _exceptions = new ConcurrentDictionary<string, ConcurrentDictionary<string, ExceptionCount>>(); 22 23 /// <summary> 24 /// Records an exception and returns true if the threshold is exceeded for that exception 25 /// </summary> Record(string testName, Exception ex)26 public bool Record(string testName, Exception ex) 27 { 28 // Converting from exception to string can be expensive so only do it once and cache the string 29 string exceptionString = ex.ToString(); 30 TraceException(testName, exceptionString); 31 32 // Get the exceptions for the current test case 33 ConcurrentDictionary<string, ExceptionCount> exceptionsForTest = _exceptions.GetOrAdd(testName, _ => new ConcurrentDictionary<string, ExceptionCount>()); 34 35 // Get the count for the current exception 36 ExceptionCount exCount = exceptionsForTest.GetOrAdd(exceptionString, _ => new ExceptionCount()); 37 38 // Increment the count 39 Interlocked.Increment(ref exCount.Count); 40 41 // If the count is over the threshold, return true 42 return TestMetrics.ExceptionThreshold.HasValue && (exCount.Count > TestMetrics.ExceptionThreshold); 43 } 44 TraceException(string testName, string exceptionString)45 private void TraceException(string testName, string exceptionString) 46 { 47 StringBuilder status = new StringBuilder(); 48 status.AppendLine("========================================================================"); 49 status.AppendLine("Exception Report"); 50 status.AppendLine("========================================================================"); 51 52 status.AppendLine(string.Format("Test: {0}", testName)); 53 status.AppendLine(exceptionString); 54 55 status.AppendLine("========================================================================"); 56 status.AppendLine("End of Exception Report"); 57 status.AppendLine("========================================================================"); 58 Trace.WriteLine(status.ToString()); 59 } 60 TraceAllExceptions()61 public void TraceAllExceptions() 62 { 63 StringBuilder status = new StringBuilder(); 64 status.AppendLine("========================================================================"); 65 status.AppendLine("All Exceptions Report"); 66 status.AppendLine("========================================================================"); 67 68 foreach (string testName in _exceptions.Keys) 69 { 70 ConcurrentDictionary<string, ExceptionCount> exceptionsForTest = _exceptions[testName]; 71 72 status.AppendLine(string.Format("Test: {0}", testName)); 73 foreach (var exceptionString in exceptionsForTest.Keys) 74 { 75 status.AppendLine(string.Format("Count: {0}", exceptionsForTest[exceptionString].Count)); 76 status.AppendLine(string.Format("Exception: {0}", exceptionString)); 77 status.AppendLine(); 78 } 79 80 status.AppendLine(); 81 status.AppendLine(); 82 } 83 84 status.AppendLine("========================================================================"); 85 status.AppendLine("End of All Exceptions Report"); 86 status.AppendLine("========================================================================"); 87 Trace.WriteLine(status.ToString()); 88 } 89 GetExceptionsCount()90 public int GetExceptionsCount() 91 { 92 int count = 0; 93 94 foreach (string testName in _exceptions.Keys) 95 { 96 ConcurrentDictionary<string, ExceptionCount> exceptionsForTest = _exceptions[testName]; 97 98 foreach (var exceptionString in exceptionsForTest.Keys) 99 { 100 count += exceptionsForTest[exceptionString].Count; 101 } 102 } 103 104 return count; 105 } 106 } 107 } 108